* src/pic16/device.c (Pics16[]): moved device descriptions to devices.inc
[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     unsigned 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     unsigned 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     unsigned 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)", pic16_get_op (pcop, NULL, 0), offset);
1588           } else {
1589             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
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 /* genUminusFloat - unary minus for floating points                */
2683 /*-----------------------------------------------------------------*/
2684 static void genUminusFloat(operand *op,operand *result)
2685 {
2686   int size ,offset =0 ;
2687   
2688     FENTRY;
2689     /* for this we just need to flip the 
2690     first it then copy the rest in place */
2691     size = AOP_SIZE(op);
2692     assert( size == AOP_SIZE(result) );
2693
2694     while(size--) {
2695       pic16_mov2f(AOP(result), AOP(op), offset);
2696       offset++;
2697     }
2698     
2699     /* toggle the MSB's highest bit */
2700     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2701 }
2702
2703 /*-----------------------------------------------------------------*/
2704 /* genUminus - unary minus code generation                         */
2705 /*-----------------------------------------------------------------*/
2706 static void genUminus (iCode *ic)
2707 {
2708   int size, i;
2709   sym_link *optype, *rtype;
2710   symbol *label;
2711   int needLabel=0;
2712
2713     FENTRY;     
2714     
2715     /* assign asmops */
2716     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2717     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2718
2719     /* if both in bit space then special case */
2720     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2721       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2722         
2723         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2724         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2725         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2726         goto release; 
2727     } 
2728
2729     optype = operandType(IC_LEFT(ic));
2730     rtype = operandType(IC_RESULT(ic));
2731
2732
2733     /* if float then do float stuff */
2734     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2735       if(IS_FIXED(optype))
2736         debugf("implement fixed16x16 type\n", 0);
2737         
2738         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2739         goto release;
2740     }
2741
2742     /* otherwise subtract from zero by taking the 2's complement */
2743     size = AOP_SIZE(IC_LEFT(ic));
2744     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2745     label = newiTempLabel ( NULL );
2746     
2747     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2748       for (i=size-1; i > 0; i--) {
2749         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2750       } // for
2751       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2752       for (i=1; i < size; i++) {
2753         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2754         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2755       } // for
2756     } else {
2757       for (i=size-1; i >= 0; i--) {
2758         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2759         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2760       } // for
2761       if (size > 1) {
2762         for (i=0; i < size-2; i++) {
2763           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2764           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2765         } // for
2766         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2767       } // if
2768       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2769     }
2770     if (needLabel)
2771       pic16_emitpLabel (label->key);
2772
2773 release:
2774     /* release the aops */
2775     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2776     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2777 }
2778
2779 #if 0
2780 /*-----------------------------------------------------------------*/
2781 /* saveRegisters - will look for a call and save the registers     */
2782 /*-----------------------------------------------------------------*/
2783 static void saveRegisters(iCode *lic) 
2784 {
2785     int i;
2786     iCode *ic;
2787     bitVect *rsave;
2788     sym_link *dtype;
2789
2790     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2791     /* look for call */
2792     for (ic = lic ; ic ; ic = ic->next) 
2793         if (ic->op == CALL || ic->op == PCALL)
2794             break;
2795
2796     if (!ic) {
2797         fprintf(stderr,"found parameter push with no function call\n");
2798         return ;
2799     }
2800
2801     /* if the registers have been saved already then
2802     do nothing */
2803     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2804         return ;
2805
2806     /* find the registers in use at this time 
2807     and push them away to safety */
2808     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2809                           ic->rUsed);
2810
2811     ic->regsSaved = 1;
2812     if (options.useXstack) {
2813         if (bitVectBitValue(rsave,R0_IDX))
2814             pic16_emitcode("mov","b,r0");
2815         pic16_emitcode("mov","r0,%s",spname);
2816         for (i = 0 ; i < pic16_nRegs ; i++) {
2817             if (bitVectBitValue(rsave,i)) {
2818                 if (i == R0_IDX)
2819                     pic16_emitcode("mov","a,b");
2820                 else
2821                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2822                 pic16_emitcode("movx","@r0,a");
2823                 pic16_emitcode("inc","r0");
2824             }
2825         }
2826         pic16_emitcode("mov","%s,r0",spname);
2827         if (bitVectBitValue(rsave,R0_IDX))
2828             pic16_emitcode("mov","r0,b");           
2829     }// else
2830     //for (i = 0 ; i < pic16_nRegs ; i++) {
2831     //    if (bitVectBitValue(rsave,i))
2832     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2833     //}
2834
2835     dtype = operandType(IC_LEFT(ic));
2836     if (currFunc && dtype && 
2837         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2838         IFFUNC_ISISR(currFunc->type) &&
2839         !ic->bankSaved) 
2840
2841         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2842
2843 }
2844 /*-----------------------------------------------------------------*/
2845 /* unsaveRegisters - pop the pushed registers                      */
2846 /*-----------------------------------------------------------------*/
2847 static void unsaveRegisters (iCode *ic)
2848 {
2849     int i;
2850     bitVect *rsave;
2851
2852     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2853     /* find the registers in use at this time 
2854     and push them away to safety */
2855     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2856                           ic->rUsed);
2857     
2858     if (options.useXstack) {
2859         pic16_emitcode("mov","r0,%s",spname);   
2860         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2861             if (bitVectBitValue(rsave,i)) {
2862                 pic16_emitcode("dec","r0");
2863                 pic16_emitcode("movx","a,@r0");
2864                 if (i == R0_IDX)
2865                     pic16_emitcode("mov","b,a");
2866                 else
2867                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2868             }       
2869
2870         }
2871         pic16_emitcode("mov","%s,r0",spname);
2872         if (bitVectBitValue(rsave,R0_IDX))
2873             pic16_emitcode("mov","r0,b");
2874     } //else
2875     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2876     //    if (bitVectBitValue(rsave,i))
2877     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2878     //}
2879
2880 }  
2881 #endif
2882
2883 #if 0  // patch 14
2884 /*-----------------------------------------------------------------*/
2885 /* pushSide -                                                      */
2886 /*-----------------------------------------------------------------*/
2887 static void pushSide(operand * oper, int size)
2888 {
2889         int offset = 0;
2890     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2891         while (size--) {
2892                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2893                 if (AOP_TYPE(oper) != AOP_REG &&
2894                     AOP_TYPE(oper) != AOP_DIR &&
2895                     strcmp(l,"a") ) {
2896                         pic16_emitcode("mov","a,%s",l);
2897                         pic16_emitcode("push","acc");
2898                 } else
2899                         pic16_emitcode("push","%s",l);
2900         }
2901 }
2902 #endif // patch 14
2903
2904 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2905 {
2906   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2907     pic16_emitpcode(POC_MOVFW, src);
2908     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2909   } else {
2910     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2911         src, pic16_popGet(AOP(op), offset)));
2912   }
2913 }
2914
2915
2916 /*-----------------------------------------------------------------*/
2917 /* assignResultValue - assign results to oper, rescall==1 is       */
2918 /*                     called from genCall() or genPcall()         */
2919 /*-----------------------------------------------------------------*/
2920 static void assignResultValue(operand * oper, int rescall)
2921 {
2922   int size = AOP_SIZE(oper);
2923   int offset=0;
2924   
2925     FENTRY2;
2926 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2927     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2928
2929     if(rescall) {
2930       /* assign result from a call/pcall function() */
2931                 
2932       /* function results are stored in a special order,
2933        * see top of file with Function return policy, or manual */
2934
2935       if(size <= 4) {
2936         /* 8-bits, result in WREG */
2937         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2938                         
2939         if(size>1) {
2940           /* 16-bits, result in PRODL:WREG */
2941           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2942         }
2943                         
2944         if(size>2) {
2945           /* 24-bits, result in PRODH:PRODL:WREG */
2946           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2947         }
2948                         
2949         if(size>3) {
2950           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2951           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2952         }
2953       
2954       } else {
2955         /* >32-bits, result on stack, and FSR0 points to beginning.
2956          * Fix stack when done */
2957         /* FIXME FIXME */
2958 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
2959         while (size--) {
2960 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2961 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2962                 
2963           popaopidx(AOP(oper), size, GpsuedoStkPtr);
2964           GpsuedoStkPtr++;
2965         }
2966                         
2967         /* fix stack */
2968         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2969         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
2970         if(STACK_MODEL_LARGE) {
2971           emitSKPNC;
2972           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
2973         }
2974       }                 
2975     } else {
2976       int areg = 0;             /* matching argument register */
2977       
2978 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
2979       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
2980
2981
2982       /* its called from genReceive (probably) -- VR */
2983       /* I hope this code will not be called from somewhere else in the future! 
2984        * We manually set the pseudo stack pointer in genReceive. - dw
2985        */
2986       if(!GpsuedoStkPtr && _G.useWreg) {
2987 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2988
2989         /* The last byte in the assignment is in W */
2990         if(areg <= GpsuedoStkPtr) {
2991           size--;
2992           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
2993           offset++;
2994 //          debugf("receive from WREG\n", 0);
2995         }
2996         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
2997       }
2998 //      GpsuedoStkPtr++;
2999       _G.stack_lat = AOP_SIZE(oper)-1;
3000
3001       while (size) {
3002         size--;
3003         GpsuedoStkPtr++;
3004         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3005 //        debugf("receive from STACK\n", 0);
3006         offset++;
3007       }
3008     }
3009 }
3010
3011
3012 /*-----------------------------------------------------------------*/
3013 /* genIpush - generate code for pushing this gets a little complex */
3014 /*-----------------------------------------------------------------*/
3015 static void genIpush (iCode *ic)
3016 {
3017 //  int size, offset=0;
3018
3019   FENTRY;
3020   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3021
3022   if(ic->parmPush) {
3023     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3024
3025     /* send to stack as normal */
3026     addSet(&_G.sendSet,ic);
3027 //    addSetHead(&_G.sendSet,ic);
3028     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3029   }
3030
3031         
3032 #if 0
3033     int size, offset = 0 ;
3034     char *l;
3035
3036
3037     /* if this is not a parm push : ie. it is spill push 
3038     and spill push is always done on the local stack */
3039     if (!ic->parmPush) {
3040
3041         /* and the item is spilt then do nothing */
3042         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3043             return ;
3044
3045         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3046         size = AOP_SIZE(IC_LEFT(ic));
3047         /* push it on the stack */
3048         while(size--) {
3049             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3050             if (*l == '#') {
3051                 MOVA(l);
3052                 l = "acc";
3053             }
3054             pic16_emitcode("push","%s",l);
3055         }
3056         return ;        
3057     }
3058
3059     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3060 #endif
3061 }
3062
3063 /*-----------------------------------------------------------------*/
3064 /* genIpop - recover the registers: can happen only for spilling   */
3065 /*-----------------------------------------------------------------*/
3066 static void genIpop (iCode *ic)
3067 {
3068   FENTRY;
3069   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3070 #if 0
3071     int size,offset ;
3072
3073
3074     /* if the temp was not pushed then */
3075     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3076         return ;
3077
3078     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3079     size = AOP_SIZE(IC_LEFT(ic));
3080     offset = (size-1);
3081     while (size--) 
3082         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3083                                    FALSE,TRUE));
3084
3085     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3086 #endif
3087 }
3088
3089 #if 0
3090 /*-----------------------------------------------------------------*/
3091 /* unsaverbank - restores the resgister bank from stack            */
3092 /*-----------------------------------------------------------------*/
3093 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3094 {
3095   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3096 #if 0
3097     int i;
3098     asmop *aop ;
3099     regs *r = NULL;
3100
3101     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3102     if (popPsw) {
3103         if (options.useXstack) {
3104             aop = newAsmop(0);
3105             r = getFreePtr(ic,&aop,FALSE);
3106             
3107             
3108             pic16_emitcode("mov","%s,_spx",r->name);
3109             pic16_emitcode("movx","a,@%s",r->name);
3110             pic16_emitcode("mov","psw,a");
3111             pic16_emitcode("dec","%s",r->name);
3112             
3113         }else
3114             pic16_emitcode ("pop","psw");
3115     }
3116
3117     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3118         if (options.useXstack) {       
3119             pic16_emitcode("movx","a,@%s",r->name);
3120             //pic16_emitcode("mov","(%s+%d),a",
3121             //       regspic16[i].base,8*bank+regspic16[i].offset);
3122             pic16_emitcode("dec","%s",r->name);
3123
3124         } else 
3125           pic16_emitcode("pop",""); //"(%s+%d)",
3126         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3127     }
3128
3129     if (options.useXstack) {
3130
3131         pic16_emitcode("mov","_spx,%s",r->name);
3132         pic16_freeAsmop(NULL,aop,ic,TRUE);
3133
3134     }
3135 #endif 
3136 }
3137
3138 /*-----------------------------------------------------------------*/
3139 /* saverbank - saves an entire register bank on the stack          */
3140 /*-----------------------------------------------------------------*/
3141 static void saverbank (int bank, iCode *ic, bool pushPsw)
3142 {
3143   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3144 #if 0
3145     int i;
3146     asmop *aop ;
3147     regs *r = NULL;
3148
3149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3150     if (options.useXstack) {
3151
3152         aop = newAsmop(0);
3153         r = getFreePtr(ic,&aop,FALSE);  
3154         pic16_emitcode("mov","%s,_spx",r->name);
3155
3156     }
3157
3158     for (i = 0 ; i < pic16_nRegs ;i++) {
3159         if (options.useXstack) {
3160             pic16_emitcode("inc","%s",r->name);
3161             //pic16_emitcode("mov","a,(%s+%d)",
3162             //         regspic16[i].base,8*bank+regspic16[i].offset);
3163             pic16_emitcode("movx","@%s,a",r->name);           
3164         } else 
3165           pic16_emitcode("push","");// "(%s+%d)",
3166                      //regspic16[i].base,8*bank+regspic16[i].offset);
3167     }
3168     
3169     if (pushPsw) {
3170         if (options.useXstack) {
3171             pic16_emitcode("mov","a,psw");
3172             pic16_emitcode("movx","@%s,a",r->name);     
3173             pic16_emitcode("inc","%s",r->name);
3174             pic16_emitcode("mov","_spx,%s",r->name);       
3175             pic16_freeAsmop (NULL,aop,ic,TRUE);
3176             
3177         } else
3178             pic16_emitcode("push","psw");
3179         
3180         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3181     }
3182     ic->bankSaved = 1;
3183 #endif
3184 }
3185 #endif  /* 0 */
3186
3187
3188 static int wparamCmp(void *p1, void *p2)
3189 {
3190   return (!strcmp((char *)p1, (char *)p2));
3191 }
3192
3193 int inWparamList(char *s)
3194 {
3195   return isinSetWith(wparamList, s, wparamCmp);
3196
3197
3198
3199 /*-----------------------------------------------------------------*/
3200 /* genCall - generates a call statement                            */
3201 /*-----------------------------------------------------------------*/
3202 static void genCall (iCode *ic)
3203 {
3204   sym_link *ftype;   
3205   int stackParms=0;
3206   int use_wreg=0;
3207   int inwparam=0;
3208   char *fname;
3209   
3210     FENTRY;
3211
3212     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3213     /* if caller saves & we have not saved then */
3214 //    if (!ic->regsSaved)
3215 //      saveRegisters(ic);
3216
3217         /* initialise stackParms for IPUSH pushes */
3218 //      stackParms = psuedoStkPtr;
3219 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3220     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3221     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3222
3223 #if 0
3224     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3225 #endif
3226
3227     /* if send set is not empty the assign */
3228     if (_G.sendSet) {
3229       iCode *sic;
3230       int psuedoStkPtr=-1; 
3231       int firstTimeThruLoop = 1;
3232
3233
3234         /* reverse sendSet if function is not reentrant */
3235         if(!IFFUNC_ISREENT(ftype))
3236           _G.sendSet = reverseSet(_G.sendSet);
3237
3238         /* First figure how many parameters are getting passed */
3239         stackParms = 0;
3240         use_wreg = 0;
3241         
3242         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3243           int size;
3244 //          int offset = 0;
3245
3246             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3247             size = AOP_SIZE(IC_LEFT(sic));
3248
3249             stackParms += size;
3250
3251             /* pass the last byte through WREG */
3252             if(inwparam) {
3253
3254               while (size--) {
3255                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3256                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3257                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3258
3259                 if(!firstTimeThruLoop) {
3260                   /* If this is not the first time we've been through the loop
3261                    * then we need to save the parameter in a temporary
3262                    * register. The last byte of the last parameter is
3263                    * passed in W. */
3264
3265                   pushw();
3266 //                  --psuedoStkPtr;             // sanity check
3267                   use_wreg = 1;
3268                 }
3269                 
3270                 firstTimeThruLoop=0;
3271
3272                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3273
3274 //                offset++;
3275               }
3276             } else {
3277               /* all arguments are passed via stack */
3278               use_wreg = 0;
3279
3280               while (size--) {
3281                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3282                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3283                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3284
3285 //                pushaop(AOP(IC_LEFT(sic)), size);
3286                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3287
3288                 if(!_G.resDirect)
3289                   pushw();
3290               }
3291             }
3292
3293             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3294           }
3295
3296           if(inwparam) {
3297             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3298               pushw();  /* save last parameter to stack if functions has varargs */
3299               use_wreg = 0;
3300             } else
3301               use_wreg = 1;
3302           } else use_wreg = 0;
3303
3304           _G.stackRegSet = _G.sendSet;
3305           _G.sendSet = NULL;
3306     }
3307
3308     /* make the call */
3309     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3310
3311     GpsuedoStkPtr=0;
3312     
3313     /* if we need to assign a result value */
3314     if ((IS_ITEMP(IC_RESULT(ic))
3315           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3316               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3317         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3318
3319       _G.accInUse++;
3320       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3321       _G.accInUse--;
3322
3323       assignResultValue(IC_RESULT(ic), 1);
3324
3325       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3326                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3327                 
3328       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3329     }
3330
3331     if(!stackParms && ic->parmBytes) {
3332       stackParms = ic->parmBytes;
3333     }
3334       
3335     stackParms -= use_wreg;
3336     
3337     if(stackParms>0) {
3338       if(stackParms == 1) {
3339         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3340       } else {
3341         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3342         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3343       }
3344       if(STACK_MODEL_LARGE) {
3345         emitSKPNC;
3346         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3347       }
3348     }
3349
3350 #if 0
3351     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3352 #endif
3353
3354     /* adjust the stack for parameters if required */
3355 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3356
3357 #if 0
3358       /* if register bank was saved then pop them */
3359       if (ic->bankSaved)
3360         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3361
3362       /* if we hade saved some registers then unsave them */
3363       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3364         unsaveRegisters (ic);
3365 #endif
3366 }
3367
3368
3369
3370 /*-----------------------------------------------------------------*/
3371 /* genPcall - generates a call by pointer statement                */
3372 /*            new version, created from genCall - HJD              */
3373 /*-----------------------------------------------------------------*/
3374 static void genPcall (iCode *ic)
3375 {
3376   sym_link *ftype, *fntype;
3377   int stackParms=0;
3378   symbol *retlbl = newiTempLabel(NULL);
3379   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3380   
3381     FENTRY;
3382
3383     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3384     fntype = operandType( IC_LEFT(ic) )->next;
3385
3386     /* if send set is not empty the assign */
3387     if (_G.sendSet) {
3388       iCode *sic;
3389       int psuedoStkPtr=-1; 
3390
3391       /* reverse sendSet if function is not reentrant */
3392       if(!IFFUNC_ISREENT(fntype))
3393         _G.sendSet = reverseSet(_G.sendSet);
3394
3395       stackParms = 0;
3396       
3397       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3398         int size;
3399
3400           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3401           size = AOP_SIZE(IC_LEFT(sic));
3402           stackParms += size;
3403
3404           /* all parameters are passed via stack, since WREG is clobbered
3405            * by the calling sequence */
3406           while (size--) {
3407             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3408             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3409             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3410
3411             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3412             pushw();
3413           }
3414
3415           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3416       }
3417
3418       _G.stackRegSet = _G.sendSet;
3419       _G.sendSet = NULL;
3420     }
3421
3422     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3423
3424     // push return address
3425     // push $ on return stack, then replace with retlbl
3426
3427     /* Thanks to Thorsten Klose for pointing out that the following
3428      * snippet should be interrupt safe */
3429     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3430     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3431
3432     pic16_emitpcodeNULLop(POC_PUSH);
3433
3434     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3435     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3436     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3437     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3438     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3439     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3440
3441
3442     /* restore interrupt control register */
3443     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3444     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3445
3446     /* make the call by writing the pointer into pc */
3447     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
3448     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
3449
3450     // note: MOVFF to PCL not allowed
3451     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
3452     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3453
3454
3455     /* return address is here: (X) */
3456     pic16_emitpLabelFORCE(retlbl->key);
3457
3458     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3459
3460     GpsuedoStkPtr=0;
3461     /* if we need assign a result value */
3462     if ((IS_ITEMP(IC_RESULT(ic))
3463           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3464               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3465         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3466
3467       _G.accInUse++;
3468       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3469       _G.accInUse--;
3470
3471       assignResultValue(IC_RESULT(ic), 1);
3472
3473       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3474               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3475                 
3476       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3477     }
3478
3479 //    stackParms -= use_wreg;
3480     
3481     if(stackParms>0) {
3482       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3483       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3484       if(STACK_MODEL_LARGE) {
3485         emitSKPNC;
3486         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3487       }
3488     }
3489 }
3490
3491 /*-----------------------------------------------------------------*/
3492 /* resultRemat - result  is rematerializable                       */
3493 /*-----------------------------------------------------------------*/
3494 static int resultRemat (iCode *ic)
3495 {
3496   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3497   if (SKIP_IC(ic) || ic->op == IFX)
3498     return 0;
3499
3500   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3501     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3502     if (sym->remat && !POINTER_SET(ic)) 
3503       return 1;
3504   }
3505
3506   return 0;
3507 }
3508
3509 #if defined(__BORLANDC__) || defined(_MSC_VER)
3510 #define STRCASECMP stricmp
3511 #else
3512 #define STRCASECMP strcasecmp
3513 #endif
3514
3515 #if 0
3516 /*-----------------------------------------------------------------*/
3517 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3518 /*-----------------------------------------------------------------*/
3519 static bool inExcludeList(char *s)
3520 {
3521   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3522     int i =0;
3523     
3524     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3525     if (options.excludeRegs[i] &&
3526     STRCASECMP(options.excludeRegs[i],"none") == 0)
3527         return FALSE ;
3528
3529     for ( i = 0 ; options.excludeRegs[i]; i++) {
3530         if (options.excludeRegs[i] &&
3531         STRCASECMP(s,options.excludeRegs[i]) == 0)
3532             return TRUE;
3533     }
3534     return FALSE ;
3535 }
3536 #endif
3537
3538 /*-----------------------------------------------------------------*/
3539 /* genFunction - generated code for function entry                 */
3540 /*-----------------------------------------------------------------*/
3541 static void genFunction (iCode *ic)
3542 {
3543   symbol *sym;
3544   sym_link *ftype;
3545   
3546     FENTRY;
3547     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3548
3549     pic16_labelOffset += (max_key+4);
3550     max_key=0;
3551     GpsuedoStkPtr=0;
3552     _G.nRegsSaved = 0;
3553         
3554     ftype = operandType(IC_LEFT(ic));
3555     sym = OP_SYMBOL(IC_LEFT(ic));
3556
3557     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3558       /* create an absolute section at the interrupt vector:
3559        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3560       symbol *asym;
3561       char asymname[128];
3562       pBlock *apb;
3563
3564 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3565
3566         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3567           sprintf(asymname, "ivec_%s", sym->name);
3568         else
3569           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3570   
3571         /* when an interrupt is declared as naked, do not emit the special
3572          * wrapper segment at vector address. The user should take care for
3573          * this instead. -- VR */
3574
3575         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3576           asym = newSymbol(asymname, 0);
3577           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3578           pic16_addpBlock( apb );
3579
3580           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3581           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3582           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3583           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3584           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3585                 
3586           /* mark the end of this tiny function */
3587           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3588         } else {
3589           sprintf(asymname, "%s", sym->rname);
3590         }
3591
3592         {
3593           absSym *abSym;
3594
3595             abSym = Safe_calloc(1, sizeof(absSym));
3596             strcpy(abSym->name, asymname);
3597
3598             switch( FUNC_INTNO(sym->type) ) {
3599               case 0: abSym->address = 0x000000; break;
3600               case 1: abSym->address = 0x000008; break;
3601               case 2: abSym->address = 0x000018; break;
3602               
3603               default:
3604 //                fprintf(stderr, "no interrupt number is given\n");
3605                 abSym->address = -1; break;
3606             }
3607
3608             /* relocate interrupt vectors if needed */
3609             if(abSym->address != -1)
3610               abSym->address += pic16_options.ivt_loc;
3611
3612             addSet(&absSymSet, abSym);
3613         }
3614     }
3615
3616     /* create the function header */
3617     pic16_emitcode(";","-----------------------------------------");
3618     pic16_emitcode(";"," function %s",sym->name);
3619     pic16_emitcode(";","-----------------------------------------");
3620
3621     pic16_emitcode("","%s:",sym->rname);
3622     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3623
3624     {
3625       absSym *ab;
3626
3627         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3628           if(!strcmp(ab->name, sym->rname)) {
3629             pic16_pBlockConvert2Absolute(pb);
3630             break;
3631           }
3632         }
3633     }
3634
3635     if(IFFUNC_ISNAKED(ftype)) {
3636       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3637       return;
3638     }
3639         
3640     /* if critical function then turn interrupts off */
3641     if (IFFUNC_ISCRITICAL(ftype)) {
3642       //pic16_emitcode("clr","ea");
3643     }
3644
3645     currFunc = sym;             /* update the currFunc symbol */
3646     _G.fregsUsed = sym->regsUsed;
3647     _G.sregsAlloc = newBitVect(128);
3648     
3649
3650     /* if this is an interrupt service routine then
3651      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3652     if (IFFUNC_ISISR(sym->type)) {
3653         _G.usefastretfie = 1;   /* use shadow registers by default */
3654         
3655         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3656         if(!FUNC_ISSHADOWREGS(sym->type)) {
3657           /* do not save WREG,STATUS,BSR for high priority interrupts
3658            * because they are stored in the hardware shadow registers already */
3659           _G.usefastretfie = 0;
3660           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3661           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3662           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3663         }
3664
3665         /* these should really be optimized somehow, because not all
3666          * interrupt handlers modify them */
3667         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3668         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3669         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3670         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3671         
3672 //        pic16_pBlockConvert2ISR(pb);
3673     }
3674
3675     /* emit code to setup stack frame if user enabled,
3676      * and function is not main() */
3677     
3678 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3679     if(strcmp(sym->name, "main")) {
3680       if(0 
3681         || !options.ommitFramePtr 
3682 //        || sym->regsUsed
3683         || IFFUNC_ARGS(sym->type)
3684         || FUNC_HASSTACKPARM(sym->etype)
3685         ) {
3686         /* setup the stack frame */
3687         if(STACK_MODEL_LARGE)
3688           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3689         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3690
3691         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3692         if(STACK_MODEL_LARGE)
3693           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3694       }
3695     }
3696
3697     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3698           && sym->stack) {
3699
3700       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3701
3702       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3703       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3704       emitSKPC;
3705       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3706     }
3707           
3708     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3709       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3710         _G.useWreg = 0;
3711       else
3712         _G.useWreg = 1;
3713     } else
3714       _G.useWreg = 0;
3715
3716     /* if callee-save to be used for this function
3717      * then save the registers being used in this function */
3718 //    if (IFFUNC_CALLEESAVES(sym->type))
3719     {
3720       int i;
3721
3722         /* if any registers used */
3723         if (sym->regsUsed) {
3724           /* save the registers used */
3725           DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3726           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3727           for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3728             if (bitVectBitValue(sym->regsUsed,i)) {
3729               pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3730               _G.nRegsSaved++;
3731
3732               if(!pic16_regWithIdx(i)->wasUsed) {
3733                 fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0d\n",
3734                               __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3735                 pic16_regWithIdx(i)->wasUsed = 1;
3736               }
3737             }
3738           }
3739           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3740         }
3741     }
3742         
3743     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3744 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3745 }
3746
3747 /*-----------------------------------------------------------------*/
3748 /* genEndFunction - generates epilogue for functions               */
3749 /*-----------------------------------------------------------------*/
3750 static void genEndFunction (iCode *ic)
3751 {
3752   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3753
3754     FENTRY;
3755
3756     if(IFFUNC_ISNAKED(sym->type)) {
3757       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3758       return;
3759     }
3760
3761     _G.stack_lat = 0;
3762
3763     /* add code for ISCRITICAL */
3764     if(IFFUNC_ISCRITICAL(sym->type)) {
3765       /* if critical function, turn on interrupts */
3766       
3767       /* TODO: add code here -- VR */
3768     }
3769     
3770 //    sym->regsUsed = _G.fregsUsed;
3771     
3772     /* now we need to restore the registers */
3773     /* if any registers used */
3774
3775     /* first restore registers that might be used for stack access */
3776     if(_G.sregsAllocSet) {
3777     regs *sr;
3778     
3779       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3780       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3781         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3782       }
3783     }
3784
3785     if (sym->regsUsed) {
3786       int i;
3787
3788         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3789         /* restore registers used */
3790         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3791         for ( i = sym->regsUsed->size; i >= 0; i--) {
3792           if (bitVectBitValue(sym->regsUsed,i)) {
3793             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3794             _G.nRegsSaved--;
3795           }
3796         }
3797         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3798     }
3799
3800       
3801
3802     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3803           && sym->stack) {
3804       if (sym->stack == 1) {
3805         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3806         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3807       } else {
3808         // we have to add more than one...
3809         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3810         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3811         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3812         emitSKPNC;
3813         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3814         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3815         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3816       }
3817     }
3818
3819     if(strcmp(sym->name, "main")) {
3820       if(0
3821         || !options.ommitFramePtr
3822 //        || sym->regsUsed
3823         || IFFUNC_ARGS(sym->type)
3824         || FUNC_HASSTACKPARM(sym->etype)
3825         ) {
3826         /* restore stack frame */
3827         if(STACK_MODEL_LARGE)
3828           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3829         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3830       }
3831     }
3832
3833     _G.useWreg = 0;
3834
3835     if (IFFUNC_ISISR(sym->type)) {
3836       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3837       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3838       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3839       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3840
3841       if(!FUNC_ISSHADOWREGS(sym->type)) {
3842         /* do not restore interrupt vector for WREG,STATUS,BSR
3843          * for high priority interrupt, see genFunction */
3844         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3845         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3846         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3847       }
3848 //      _G.interruptvector = 0;         /* sanity check */
3849
3850
3851       /* if debug then send end of function */
3852 /*      if (options.debug && currFunc)  */
3853       if (currFunc) {
3854         debugFile->writeEndFunction (currFunc, ic, 1);
3855       }
3856         
3857       if(_G.usefastretfie)
3858         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3859       else
3860         pic16_emitpcodeNULLop(POC_RETFIE);
3861
3862       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3863       
3864       _G.usefastretfie = 0;
3865       return;
3866     }
3867
3868     if (IFFUNC_ISCRITICAL(sym->type)) {
3869       pic16_emitcode("setb","ea");
3870     }
3871
3872     /* if debug then send end of function */
3873     if (currFunc) {
3874       debugFile->writeEndFunction (currFunc, ic, 1);
3875     }
3876
3877     /* insert code to restore stack frame, if user enabled it
3878      * and function is not main() */
3879          
3880
3881     pic16_emitpcodeNULLop(POC_RETURN);
3882
3883     /* Mark the end of a function */
3884     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3885 }
3886
3887
3888 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3889 {
3890   unsigned long lit=1;
3891   operand *op;
3892
3893     op = IC_LEFT(ic);
3894   
3895     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3896     if(AOP_TYPE(op) == AOP_LIT) {
3897       if(!IS_FLOAT(operandType( op ))) {
3898         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3899       } else {
3900         union {
3901           unsigned long lit_int;
3902           float lit_float;
3903         } info;
3904         
3905         /* take care if literal is a float */
3906         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3907         lit = info.lit_int;
3908       }
3909     }
3910
3911     if(is_LitOp(op)) {
3912       if(/*(OP_LIVETO(op) <= ic->seq) &&*/ (lit == 0)) {
3913         pic16_emitpcode(POC_CLRF, dest);
3914       } else {
3915         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset));
3916         if(dest->type != PO_WREG)pic16_emitpcode(POC_MOVWF, dest);
3917       }
3918     } else {
3919       if(dest->type == PO_WREG && (offset == 0)) {
3920         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
3921       return;
3922     }
3923     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
3924   }
3925 }
3926
3927 /*-----------------------------------------------------------------*/
3928 /* genRet - generate code for return statement                     */
3929 /*-----------------------------------------------------------------*/
3930 static void genRet (iCode *ic)
3931 {
3932   int size;
3933   operand *left;
3934
3935     FENTRY;
3936         /* if we have no return value then
3937          * just generate the "ret" */
3938         
3939         if (!IC_LEFT(ic)) 
3940                 goto jumpret;       
3941     
3942         /* we have something to return then
3943          * move the return value into place */
3944         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3945         size = AOP_SIZE(IC_LEFT(ic));
3946
3947         if(size <= 4) {
3948           if(size>3)
3949             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3950           
3951           if(size>2)
3952             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
3953
3954           if(size>1)
3955             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
3956           
3957           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
3958
3959         } else {
3960                 /* >32-bits, setup stack and FSR0 */
3961                 while (size--) {
3962 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3963 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3964
3965                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3966
3967 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3968                         GpsuedoStkPtr++;
3969                 }
3970                         
3971                 /* setup FSR0 */
3972                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3973                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
3974
3975                 if(STACK_MODEL_LARGE) {
3976                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3977                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
3978                 } else {
3979                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
3980                 }
3981         }
3982                                 
3983 #if 0
3984         /* old code, left here for reference -- VR */    
3985         while (size--) {
3986           char *l ;
3987
3988                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3989                         /* #NOCHANGE */
3990                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3991                         pic16_emitpcomment("push %s",l);
3992                         pushed++;
3993                 } else {
3994                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3995                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3996                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3997                         
3998                         if (strcmp(fReturn[offset],l)) {
3999                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4000                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4001                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4002                                 } else {
4003                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4004                                 }
4005                                 
4006                                 if(size) {
4007                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4008                                 }
4009                                 offset++;
4010                         }
4011                 }
4012         }    
4013
4014         if (pushed) {
4015                 while(pushed) {
4016                         pushed--;
4017                         if (strcmp(fReturn[pushed],"a"))
4018                                 pic16_emitcode("pop",fReturn[pushed]);
4019                         else
4020                                 pic16_emitcode("pop","acc");
4021                 }
4022         }
4023 #endif
4024
4025
4026         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4027     
4028 jumpret:
4029         /* generate a jump to the return label
4030          * if the next is not the return statement */
4031         if (!(ic->next && ic->next->op == LABEL
4032                 && IC_LABEL(ic->next) == returnLabel)) {
4033         
4034                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4035                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4036         }
4037 }
4038
4039 /*-----------------------------------------------------------------*/
4040 /* genLabel - generates a label                                    */
4041 /*-----------------------------------------------------------------*/
4042 static void genLabel (iCode *ic)
4043 {
4044   FENTRY;
4045
4046   /* special case never generate */
4047   if (IC_LABEL(ic) == entryLabel)
4048     return ;
4049
4050   pic16_emitpLabel(IC_LABEL(ic)->key);
4051 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4052 }
4053
4054 /*-----------------------------------------------------------------*/
4055 /* genGoto - generates a goto                                      */
4056 /*-----------------------------------------------------------------*/
4057 //tsd
4058 static void genGoto (iCode *ic)
4059 {
4060   FENTRY;
4061   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4062 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4063 }
4064
4065
4066 /*-----------------------------------------------------------------*/
4067 /* genMultbits :- multiplication of bits                           */
4068 /*-----------------------------------------------------------------*/
4069 static void genMultbits (operand *left, 
4070                          operand *right, 
4071                          operand *result)
4072 {
4073   FENTRY;
4074
4075   if(!pic16_sameRegs(AOP(result),AOP(right)))
4076     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4077
4078   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4079   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4080   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4081
4082 }
4083
4084
4085 /*-----------------------------------------------------------------*/
4086 /* genMultOneByte : 8 bit multiplication & division                */
4087 /*-----------------------------------------------------------------*/
4088 static void genMultOneByte (operand *left,
4089                             operand *right,
4090                             operand *result)
4091 {
4092
4093   FENTRY;
4094   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4095   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4096
4097   /* (if two literals, the value is computed before) */
4098   /* if one literal, literal on the right */
4099   if (AOP_TYPE(left) == AOP_LIT){
4100     operand *t = right;
4101     right = left;
4102     left = t;
4103   }
4104
4105         /* size is already checked in genMult == 1 */
4106 //      size = AOP_SIZE(result);
4107
4108         if (AOP_TYPE(right) == AOP_LIT){
4109                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4110                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4111                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4112                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4113         } else {
4114                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4115                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4116                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4117                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4118         }
4119         
4120         pic16_genMult8X8_8 (left, right,result);
4121 }
4122
4123 /*-----------------------------------------------------------------*/
4124 /* genMultOneWord : 16 bit multiplication                          */
4125 /*-----------------------------------------------------------------*/
4126 static void genMultOneWord (operand *left,
4127                             operand *right,
4128                             operand *result)
4129 {
4130   FENTRY;
4131   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4132   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4133
4134   /* (if two literals, the value is computed before)
4135    * if one literal, literal on the right */
4136   if (AOP_TYPE(left) == AOP_LIT){
4137     operand *t = right;
4138     right = left;
4139     left = t;
4140   }
4141
4142   /* size is checked already == 2 */
4143 //  size = AOP_SIZE(result);
4144
4145   if (AOP_TYPE(right) == AOP_LIT) {
4146     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4147       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4148       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4149       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4150   } else {
4151     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4152       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4153       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4154       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4155   }
4156         
4157   pic16_genMult16X16_16(left, right,result);
4158 }
4159
4160 /*-----------------------------------------------------------------*/
4161 /* genMultOneLong : 32 bit multiplication                          */
4162 /*-----------------------------------------------------------------*/
4163 static void genMultOneLong (operand *left,
4164                             operand *right,
4165                             operand *result)
4166 {
4167   FENTRY;
4168   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4169   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4170
4171   /* (if two literals, the value is computed before)
4172    * if one literal, literal on the right */
4173   if (AOP_TYPE(left) == AOP_LIT){
4174     operand *t = right;
4175     right = left;
4176     left = t;
4177   }
4178
4179   /* size is checked already == 4 */
4180 //  size = AOP_SIZE(result);
4181
4182   if (AOP_TYPE(right) == AOP_LIT) {
4183     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4184         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4185         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4186         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4187   } else {
4188     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4189         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4190         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4191         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4192   }
4193         
4194   pic16_genMult32X32_32(left, right,result);
4195 }
4196
4197
4198
4199 /*-----------------------------------------------------------------*/
4200 /* genMult - generates code for multiplication                     */
4201 /*-----------------------------------------------------------------*/
4202 static void genMult (iCode *ic)
4203 {
4204   operand *left = IC_LEFT(ic);
4205   operand *right = IC_RIGHT(ic);
4206   operand *result= IC_RESULT(ic);   
4207
4208     FENTRY;
4209         /* assign the amsops */
4210         pic16_aopOp (left,ic,FALSE);
4211         pic16_aopOp (right,ic,FALSE);
4212         pic16_aopOp (result,ic,TRUE);
4213
4214         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4215
4216         /* special cases first *
4217         * both are bits */
4218         if (AOP_TYPE(left) == AOP_CRY
4219                 && AOP_TYPE(right)== AOP_CRY) {
4220                 genMultbits(left,right,result);
4221           goto release ;
4222         }
4223
4224         /* if both are of size == 1 */
4225         if(AOP_SIZE(left) == 1
4226                 && AOP_SIZE(right) == 1) {
4227                 genMultOneByte(left,right,result);
4228           goto release ;
4229         }
4230
4231         /* if both are of size == 2 */
4232         if(AOP_SIZE(left) == 2
4233                 && AOP_SIZE(right) == 2) {
4234                 genMultOneWord(left, right, result);
4235           goto release;
4236         }
4237         
4238         /* if both are of size == 4 */
4239         if(AOP_SIZE(left) == 4
4240                 && AOP_SIZE(right) == 4) {
4241                 genMultOneLong(left, right, result);
4242           goto release;
4243         }
4244         
4245         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4246
4247
4248         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4249         /* should have been converted to function call */
4250         assert(0) ;
4251
4252 release :
4253         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4254         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4255         pic16_freeAsmop(result,NULL,ic,TRUE); 
4256 }
4257
4258 /*-----------------------------------------------------------------*/
4259 /* genDivbits :- division of bits                                  */
4260 /*-----------------------------------------------------------------*/
4261 static void genDivbits (operand *left, 
4262                         operand *right, 
4263                         operand *result)
4264 {
4265   char *l;
4266
4267     FENTRY;
4268     /* the result must be bit */    
4269     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4270     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4271
4272     MOVA(l);    
4273
4274     pic16_emitcode("div","ab");
4275     pic16_emitcode("rrc","a");
4276     pic16_aopPut(AOP(result),"c",0);
4277 }
4278
4279 /*-----------------------------------------------------------------*/
4280 /* genDivOneByte : 8 bit division                                  */
4281 /*-----------------------------------------------------------------*/
4282 static void genDivOneByte (operand *left,
4283                            operand *right,
4284                            operand *result)
4285 {
4286   sym_link *opetype = operandType(result);
4287   char *l ;
4288   symbol *lbl ;
4289   int size,offset;
4290
4291         /* result = divident / divisor
4292          * - divident may be a register or a literal,
4293          * - divisor may be a register or a literal,
4294          * so there are 3 cases (literal / literal is optimized
4295          * by the front-end) to handle.
4296          * In addition we must handle signed and unsigned, which
4297          * result in 6 final different cases -- VR */
4298
4299     FENTRY;
4300     
4301     size = AOP_SIZE(result) - 1;
4302     offset = 1;
4303     /* signed or unsigned */
4304     if (SPEC_USIGN(opetype)) {
4305       pCodeOp *pct1,    /* count */
4306                 *pct2,  /* reste */
4307                 *pct3;  /* temp */
4308       symbol *label1, *label2, *label3;;
4309
4310
4311         /* unsigned is easy */
4312
4313         pct1 = pic16_popGetTempReg(1);
4314         pct2 = pic16_popGetTempReg(1);
4315         pct3 = pic16_popGetTempReg(1);
4316         
4317         label1 = newiTempLabel(NULL);
4318         label2 = newiTempLabel(NULL);
4319         label3 = newiTempLabel(NULL);
4320
4321         /* the following algorithm is extracted from divuint.c */
4322
4323         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4324         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4325         
4326         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4327
4328         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4329         
4330         pic16_emitpLabel(label1->key);
4331         
4332         emitCLRC;
4333         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4334
4335
4336         emitCLRC;
4337         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4338         
4339
4340         emitSKPNC;
4341         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4342         
4343         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4344         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4345         
4346         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4347         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4348         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4349         
4350         pic16_emitpLabel( label3->key );
4351         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4352         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4353         
4354         
4355
4356         pic16_emitpLabel(label2->key);
4357         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4358         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4359         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4360         
4361         /* result is in wreg */
4362         if(AOP_TYPE(result) != AOP_ACC)
4363                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4364
4365         pic16_popReleaseTempReg( pct3, 1);
4366         pic16_popReleaseTempReg( pct2, 1);
4367         pic16_popReleaseTempReg( pct1, 1);
4368
4369         return ;
4370     }
4371
4372     /* signed is a little bit more difficult */
4373
4374     /* save the signs of the operands */
4375     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4376     MOVA(l);    
4377     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4378     pic16_emitcode("push","acc"); /* save it on the stack */
4379
4380     /* now sign adjust for both left & right */
4381     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4382     MOVA(l);       
4383     lbl = newiTempLabel(NULL);
4384     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4385     pic16_emitcode("cpl","a");   
4386     pic16_emitcode("inc","a");
4387     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4388     pic16_emitcode("mov","b,a");
4389
4390     /* sign adjust left side */
4391     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4392     MOVA(l);
4393
4394     lbl = newiTempLabel(NULL);
4395     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4396     pic16_emitcode("cpl","a");
4397     pic16_emitcode("inc","a");
4398     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4399
4400     /* now the division */
4401     pic16_emitcode("div","ab");
4402     /* we are interested in the lower order
4403     only */
4404     pic16_emitcode("mov","b,a");
4405     lbl = newiTempLabel(NULL);
4406     pic16_emitcode("pop","acc");   
4407     /* if there was an over flow we don't 
4408     adjust the sign of the result */
4409     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4410     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4411     CLRC;
4412     pic16_emitcode("clr","a");
4413     pic16_emitcode("subb","a,b");
4414     pic16_emitcode("mov","b,a");
4415     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4416
4417     /* now we are done */
4418     pic16_aopPut(AOP(result),"b",0);
4419     if(size > 0){
4420         pic16_emitcode("mov","c,b.7");
4421         pic16_emitcode("subb","a,acc");   
4422     }
4423     while (size--)
4424         pic16_aopPut(AOP(result),"a",offset++);
4425
4426 }
4427
4428 /*-----------------------------------------------------------------*/
4429 /* genDiv - generates code for division                            */
4430 /*-----------------------------------------------------------------*/
4431 static void genDiv (iCode *ic)
4432 {
4433     operand *left = IC_LEFT(ic);
4434     operand *right = IC_RIGHT(ic);
4435     operand *result= IC_RESULT(ic);   
4436
4437
4438         /* Division is a very lengthy algorithm, so it is better
4439          * to call support routines than inlining algorithm.
4440          * Division functions written here just in case someone
4441          * wants to inline and not use the support libraries -- VR */
4442
4443     FENTRY;
4444     
4445     /* assign the amsops */
4446     pic16_aopOp (left,ic,FALSE);
4447     pic16_aopOp (right,ic,FALSE);
4448     pic16_aopOp (result,ic,TRUE);
4449
4450     /* special cases first */
4451     /* both are bits */
4452     if (AOP_TYPE(left) == AOP_CRY &&
4453         AOP_TYPE(right)== AOP_CRY) {
4454         genDivbits(left,right,result);
4455         goto release ;
4456     }
4457
4458     /* if both are of size == 1 */
4459     if (AOP_SIZE(left) == 1 &&
4460         AOP_SIZE(right) == 1 ) {
4461         genDivOneByte(left,right,result);
4462         goto release ;
4463     }
4464
4465     /* should have been converted to function call */
4466     assert(0);
4467 release :
4468     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4469     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4470     pic16_freeAsmop(result,NULL,ic,TRUE); 
4471 }
4472
4473 /*-----------------------------------------------------------------*/
4474 /* genModbits :- modulus of bits                                   */
4475 /*-----------------------------------------------------------------*/
4476 static void genModbits (operand *left, 
4477                         operand *right, 
4478                         operand *result)
4479 {
4480   char *l;
4481
4482     FENTRY;  
4483     
4484     werror(W_POSSBUG2, __FILE__, __LINE__);
4485     /* the result must be bit */    
4486     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4487     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4488
4489     MOVA(l);       
4490
4491     pic16_emitcode("div","ab");
4492     pic16_emitcode("mov","a,b");
4493     pic16_emitcode("rrc","a");
4494     pic16_aopPut(AOP(result),"c",0);
4495 }
4496
4497 /*-----------------------------------------------------------------*/
4498 /* genModOneByte : 8 bit modulus                                   */
4499 /*-----------------------------------------------------------------*/
4500 static void genModOneByte (operand *left,
4501                            operand *right,
4502                            operand *result)
4503 {
4504   sym_link *opetype = operandType(result);
4505   char *l ;
4506   symbol *lbl ;
4507
4508     FENTRY;
4509     werror(W_POSSBUG2, __FILE__, __LINE__);
4510
4511     /* signed or unsigned */
4512     if (SPEC_USIGN(opetype)) {
4513         /* unsigned is easy */
4514         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4515         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4516         MOVA(l);    
4517         pic16_emitcode("div","ab");
4518         pic16_aopPut(AOP(result),"b",0);
4519         return ;
4520     }
4521
4522     /* signed is a little bit more difficult */
4523
4524     /* save the signs of the operands */
4525     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4526     MOVA(l);
4527
4528     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4529     pic16_emitcode("push","acc"); /* save it on the stack */
4530
4531     /* now sign adjust for both left & right */
4532     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4533     MOVA(l);
4534
4535     lbl = newiTempLabel(NULL);
4536     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4537     pic16_emitcode("cpl","a");   
4538     pic16_emitcode("inc","a");
4539     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4540     pic16_emitcode("mov","b,a"); 
4541
4542     /* sign adjust left side */
4543     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4544     MOVA(l);
4545
4546     lbl = newiTempLabel(NULL);
4547     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4548     pic16_emitcode("cpl","a");   
4549     pic16_emitcode("inc","a");
4550     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4551
4552     /* now the multiplication */
4553     pic16_emitcode("div","ab");
4554     /* we are interested in the lower order
4555     only */
4556     lbl = newiTempLabel(NULL);
4557     pic16_emitcode("pop","acc");   
4558     /* if there was an over flow we don't 
4559     adjust the sign of the result */
4560     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4561     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4562     CLRC ;
4563     pic16_emitcode("clr","a");
4564     pic16_emitcode("subb","a,b");
4565     pic16_emitcode("mov","b,a");
4566     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4567
4568     /* now we are done */
4569     pic16_aopPut(AOP(result),"b",0);
4570
4571 }
4572
4573 /*-----------------------------------------------------------------*/
4574 /* genMod - generates code for division                            */
4575 /*-----------------------------------------------------------------*/
4576 static void genMod (iCode *ic)
4577 {
4578   operand *left = IC_LEFT(ic);
4579   operand *right = IC_RIGHT(ic);
4580   operand *result= IC_RESULT(ic);  
4581
4582     FENTRY;
4583     
4584     /* assign the amsops */
4585     pic16_aopOp (left,ic,FALSE);
4586     pic16_aopOp (right,ic,FALSE);
4587     pic16_aopOp (result,ic,TRUE);
4588
4589     /* special cases first */
4590     /* both are bits */
4591     if (AOP_TYPE(left) == AOP_CRY &&
4592         AOP_TYPE(right)== AOP_CRY) {
4593         genModbits(left,right,result);
4594         goto release ;
4595     }
4596
4597     /* if both are of size == 1 */
4598     if (AOP_SIZE(left) == 1 &&
4599         AOP_SIZE(right) == 1 ) {
4600         genModOneByte(left,right,result);
4601         goto release ;
4602     }
4603
4604     /* should have been converted to function call */
4605     assert(0);
4606
4607 release :
4608     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4609     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4610     pic16_freeAsmop(result,NULL,ic,TRUE); 
4611 }
4612
4613 /*-----------------------------------------------------------------*/
4614 /* genIfxJump :- will create a jump depending on the ifx           */
4615 /*-----------------------------------------------------------------*/
4616 /*
4617   note: May need to add parameter to indicate when a variable is in bit space.
4618 */
4619 static void genIfxJump (iCode *ic, char *jval)
4620 {
4621   FENTRY;
4622   
4623     /* if true label then we jump if condition
4624     supplied is true */
4625     if ( IC_TRUE(ic) ) {
4626
4627         if(strcmp(jval,"a") == 0)
4628           emitSKPZ;
4629         else if (strcmp(jval,"c") == 0)
4630           emitSKPNC;
4631         else {
4632           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4633           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4634         }
4635
4636         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4637         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4638
4639     }
4640     else {
4641         /* false label is present */
4642         if(strcmp(jval,"a") == 0)
4643           emitSKPNZ;
4644         else if (strcmp(jval,"c") == 0)
4645           emitSKPC;
4646         else {
4647           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4648           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4649         }
4650
4651         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4652         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4653
4654     }
4655
4656
4657     /* mark the icode as generated */
4658     ic->generated = 1;
4659 }
4660
4661 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4662 {
4663   FENTRY;
4664   
4665     /* if true label then we jump if condition
4666     supplied is true */
4667     if ( IC_TRUE(ic) ) {
4668       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4669       pic16_emitpcode(POC_BTFSC, jop);
4670
4671       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4672       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4673
4674     } else {
4675       /* false label is present */
4676       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4677       pic16_emitpcode(POC_BTFSS, jop);
4678           
4679       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4680       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4681     }
4682
4683
4684     /* mark the icode as generated */
4685     ic->generated = 1;
4686 }
4687
4688 #if 0
4689 // not needed ATM
4690
4691 /*-----------------------------------------------------------------*/
4692 /* genSkip                                                         */
4693 /*-----------------------------------------------------------------*/
4694 static void genSkip(iCode *ifx,int status_bit)
4695 {
4696   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4697   if(!ifx)
4698     return;
4699
4700   if ( IC_TRUE(ifx) ) {
4701     switch(status_bit) {
4702     case 'z':
4703       emitSKPNZ;
4704       break;
4705
4706     case 'c':
4707       emitSKPNC;
4708       break;
4709
4710     case 'd':
4711       emitSKPDC;
4712       break;
4713
4714     }
4715
4716     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4717     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4718
4719   } else {
4720
4721     switch(status_bit) {
4722
4723     case 'z':
4724       emitSKPZ;
4725       break;
4726
4727     case 'c':
4728       emitSKPC;
4729       break;
4730
4731     case 'd':
4732       emitSKPDC;
4733       break;
4734     }
4735     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4736     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4737
4738   }
4739
4740 }
4741 #endif
4742
4743 /*-----------------------------------------------------------------*/
4744 /* genSkipc                                                        */
4745 /*-----------------------------------------------------------------*/
4746 static void genSkipc(resolvedIfx *rifx)
4747 {
4748   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4749   
4750   if(!rifx)
4751     return;
4752
4753   if(rifx->condition)
4754     emitSKPNC;
4755   else
4756     emitSKPC;
4757
4758   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4759   rifx->generated = 1;
4760 }
4761
4762 #if !(USE_SIMPLE_GENCMP)
4763 /*-----------------------------------------------------------------*/
4764 /* genSkipz2                                                       */
4765 /*-----------------------------------------------------------------*/
4766 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4767 {
4768   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4769   
4770   if(!rifx)
4771     return;
4772
4773   if( (rifx->condition ^ invert_condition) & 1)
4774     emitSKPZ;
4775   else
4776     emitSKPNZ;
4777
4778   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4779   rifx->generated = 1;
4780 }
4781 #endif
4782
4783 #if 0
4784 /*-----------------------------------------------------------------*/
4785 /* genSkipz                                                        */
4786 /*-----------------------------------------------------------------*/
4787 static void genSkipz(iCode *ifx, int condition)
4788 {
4789   if(!ifx)
4790     return;
4791
4792   if(condition)
4793     emitSKPNZ;
4794   else
4795     emitSKPZ;
4796
4797   if ( IC_TRUE(ifx) )
4798     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4799   else
4800     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4801
4802   if ( IC_TRUE(ifx) )
4803     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4804   else
4805     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4806
4807 }
4808 #endif
4809
4810 #if !(USE_SIMPLE_GENCMP)
4811 /*-----------------------------------------------------------------*/
4812 /* genSkipCond                                                     */
4813 /*-----------------------------------------------------------------*/
4814 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4815 {
4816   if(!rifx)
4817     return;
4818
4819   if(rifx->condition)
4820     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4821   else
4822     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4823
4824
4825   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4826   rifx->generated = 1;
4827 }
4828 #endif
4829
4830 #if 0
4831 /*-----------------------------------------------------------------*/
4832 /* genChkZeroes :- greater or less than comparison                 */
4833 /*     For each byte in a literal that is zero, inclusive or the   */
4834 /*     the corresponding byte in the operand with W                */
4835 /*     returns true if any of the bytes are zero                   */
4836 /*-----------------------------------------------------------------*/
4837 static int genChkZeroes(operand *op, int lit,  int size)
4838 {
4839
4840   int i;
4841   int flag =1;
4842
4843   while(size--) {
4844     i = (lit >> (size*8)) & 0xff;
4845
4846     if(i==0) {
4847       if(flag) 
4848         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4849       else
4850         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4851       flag = 0;
4852     }
4853   }
4854
4855   return (flag==0);
4856 }
4857 #endif
4858
4859
4860 /*-----------------------------------------------------------------*/
4861 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4862 /*                  aop (if it's NOT a literal) or from lit (if    */
4863 /*                  aop is a literal)                              */
4864 /*-----------------------------------------------------------------*/
4865 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4866   if (aop->type == AOP_LIT) {
4867     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4868   } else {
4869     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4870   }
4871 }
4872
4873 /*-----------------------------------------------------------------*/
4874 /* genCmp :- greater or less than comparison                       */
4875 /*-----------------------------------------------------------------*/
4876
4877 #if USE_SIMPLE_GENCMP           /* { */
4878
4879 /* genCmp performs a left < right comparison, stores
4880  * the outcome in result (if != NULL) and generates
4881  * control flow code for the ifx (if != NULL).
4882  *
4883  * This version leaves in sequences like
4884  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4885  * which should be optmized by the peephole
4886  * optimizer - RN 2005-01-01 */
4887 static void genCmp (operand *left,operand *right,
4888                     operand *result, iCode *ifx, int sign)
4889 {
4890   resolvedIfx rIfx;
4891   int size;
4892   int offs;
4893   symbol *templbl;
4894   operand *dummy;
4895   unsigned long lit;
4896   unsigned long mask;
4897   int performedLt;
4898
4899   FENTRY;
4900   
4901   assert (left && right);
4902   assert (AOP_SIZE(left) == AOP_SIZE(right));
4903
4904   size = AOP_SIZE(right) - 1;
4905   mask = (0x100UL << (size*8)) - 1;
4906   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
4907   performedLt = 1;
4908   templbl = NULL;
4909   lit = 0;
4910   
4911   resolveIfx (&rIfx, ifx);
4912
4913   /* handle for special cases */
4914   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
4915       return;
4916
4917   /**********************************************************************
4918    * handle bits - bit compares are promoted to int compares seemingly! *
4919    **********************************************************************/
4920 #if 0
4921   // THIS IS COMPLETELY UNTESTED!
4922   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
4923     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
4924     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
4925     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
4926
4927     emitSETC;
4928     // 1 < {0,1} is false --> clear C by skipping the next instruction
4929     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
4930     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
4931     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
4932     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
4933     emitCLRC; // only skipped for left=0 && right=1
4934
4935     goto correct_result_in_carry;
4936   } // if
4937 #endif
4938
4939   /*************************************************
4940    * make sure that left is register (or the like) *
4941    *************************************************/
4942   if (!isAOP_REGlike(left)) {
4943     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
4944     assert (isAOP_LIT(left));
4945     assert (isAOP_REGlike(right));
4946     // swap left and right
4947     // left < right <==> right > left <==> (right >= left + 1)
4948     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4949
4950     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
4951       // MAXVALUE < right? always false
4952       if (performedLt) emitCLRC; else emitSETC;
4953       goto correct_result_in_carry;
4954     } // if
4955
4956     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
4957     // that's why we handled it above.
4958     lit++;
4959
4960     dummy = left;
4961     left = right;
4962     right = dummy;
4963
4964     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
4965   } else if (isAOP_LIT(right)) {
4966     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4967   } // if
4968
4969   assert (isAOP_REGlike(left)); // left must be register or the like
4970   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
4971
4972   /*************************************************
4973    * special cases go here                         *
4974    *************************************************/
4975
4976   if (isAOP_LIT(right)) {
4977     if (!sign) {
4978       // unsigned comparison to a literal
4979       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
4980       if (lit == 0) {
4981         // unsigned left < 0? always false
4982         if (performedLt) emitCLRC; else emitSETC;
4983         goto correct_result_in_carry;
4984       }
4985     } else {
4986       // signed comparison to a literal
4987       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
4988       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
4989         // signed left < 0x80000000? always false
4990         if (performedLt) emitCLRC; else emitSETC;
4991         goto correct_result_in_carry;
4992       } else if (lit == 0) {
4993         // compare left < 0; set CARRY if SIGNBIT(left) is set
4994         if (performedLt) emitSETC; else emitCLRC;
4995         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
4996         if (performedLt) emitCLRC; else emitSETC;
4997         goto correct_result_in_carry;
4998       }
4999     } // if (!sign)
5000   } // right is literal
5001
5002   /*************************************************
5003    * perform a general case comparison             *
5004    * make sure we get CARRY==1 <==> left >= right  *
5005    *************************************************/
5006   // compare most significant bytes
5007   //DEBUGpc ("comparing bytes at offset %d", size);
5008   if (!sign) {
5009     // unsigned comparison
5010     mov2w_regOrLit (AOP(right), lit, size);
5011     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5012   } else {
5013     // signed comparison
5014     // (add 2^n to both operands then perform an unsigned comparison)
5015     if (isAOP_LIT(right)) {
5016       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5017       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5018
5019       if (litbyte == 0x80) {
5020         // left >= 0x80 -- always true, but more bytes to come
5021         pic16_mov2w (AOP(left), size);
5022         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5023         emitSETC;
5024       } else {
5025         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5026         pic16_mov2w (AOP(left), size);
5027         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5028         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5029       } // if
5030     } else {
5031       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5032       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5033       pic16_mov2w (AOP(left), size);
5034       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5035       pic16_emitpcode (POC_MOVWF, pctemp);
5036       pic16_mov2w (AOP(right), size);
5037       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5038       pic16_emitpcode (POC_SUBFW, pctemp);
5039       //pic16_popReleaseTempReg(pctemp, 1);
5040     }
5041   } // if (!sign)
5042
5043   // compare remaining bytes (treat as unsigned case from above)
5044   templbl = newiTempLabel ( NULL );
5045   offs = size;
5046   while (offs--) {
5047     //DEBUGpc ("comparing bytes at offset %d", offs);
5048     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5049     mov2w_regOrLit (AOP(right), lit, offs);
5050     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5051   } // while (offs)
5052   pic16_emitpLabel (templbl->key);
5053   goto result_in_carry;
5054
5055 result_in_carry:
5056   
5057   /****************************************************
5058    * now CARRY contains the result of the comparison: *
5059    * SUBWF sets CARRY iff                             *
5060    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5061    * (F=left, W=right)                                *
5062    ****************************************************/
5063
5064   if (performedLt) {
5065     if (result && AOP_TYPE(result) != AOP_CRY) {
5066       // value will be stored
5067       emitTOGC;
5068     } else {
5069       // value wil only be used in the following genSkipc()
5070       rIfx.condition ^= 1;
5071     }
5072   } // if
5073
5074 correct_result_in_carry:
5075
5076   // assign result to variable (if neccessary)
5077   if (result && AOP_TYPE(result) != AOP_CRY) {
5078     //DEBUGpc ("assign result");
5079     size = AOP_SIZE(result);
5080     while (size--) {
5081       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5082     } // while
5083     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5084   } // if (result)
5085
5086   // perform conditional jump
5087   if (ifx) {
5088     //DEBUGpc ("generate control flow");
5089     genSkipc (&rIfx);
5090     ifx->generated = 1;
5091   } // if
5092 }
5093
5094 #elif 1         /* } */
5095                 /* { */
5096       /* original code */
5097 static void genCmp (operand *left,operand *right,
5098                     operand *result, iCode *ifx, int sign)
5099 {
5100   int size; //, offset = 0 ;
5101   unsigned long lit = 0L,i = 0;
5102   resolvedIfx rFalseIfx;
5103   //  resolvedIfx rTrueIfx;
5104   symbol *truelbl;
5105   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5106 /*
5107   if(ifx) {
5108     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5109     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5110   }
5111 */
5112
5113   FENTRY;
5114   
5115   resolveIfx(&rFalseIfx,ifx);
5116   truelbl  = newiTempLabel(NULL);
5117   size = max(AOP_SIZE(left),AOP_SIZE(right));
5118
5119   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5120
5121 #define _swapp
5122
5123   /* if literal is on the right then swap with left */
5124   if ((AOP_TYPE(right) == AOP_LIT)) {
5125     operand *tmp = right ;
5126     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5127     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5128 #ifdef _swapp
5129
5130     lit = (lit - 1) & mask;
5131     right = left;
5132     left = tmp;
5133     rFalseIfx.condition ^= 1;
5134 #endif
5135
5136   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5137     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5138   }
5139
5140
5141   //if(IC_TRUE(ifx) == NULL)
5142   /* if left & right are bit variables */
5143   if (AOP_TYPE(left) == AOP_CRY &&
5144       AOP_TYPE(right) == AOP_CRY ) {
5145     assert (0 && "bit variables used in genCmp");
5146     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5147     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5148   } else {
5149     /* subtract right from left if at the
5150        end the carry flag is set then we know that
5151        left is greater than right */
5152
5153     symbol *lbl  = newiTempLabel(NULL);
5154
5155 #if 0
5156         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5157                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5158 #endif
5159
5160 #ifndef _swapp
5161     if(AOP_TYPE(right) == AOP_LIT) {
5162
5163       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5164
5165       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5166
5167       /* special cases */
5168
5169       if(lit == 0) {
5170
5171         if(sign != 0) 
5172           genSkipCond(&rFalseIfx,left,size-1,7);
5173         else 
5174           /* no need to compare to 0...*/
5175           /* NOTE: this is a de-generate compare that most certainly 
5176            *       creates some dead code. */
5177           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5178
5179         if(ifx) ifx->generated = 1;
5180         return;
5181
5182       }
5183       size--;
5184
5185       if(size == 0) {
5186         //i = (lit >> (size*8)) & 0xff;
5187         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5188         
5189         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5190
5191         i = ((0-lit) & 0xff);
5192         if(sign) {
5193           if( i == 0x81) { 
5194             /* lit is 0x7f, all signed chars are less than
5195              * this except for 0x7f itself */
5196             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5197             genSkipz2(&rFalseIfx,0);
5198           } else {
5199             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5200             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5201             genSkipc(&rFalseIfx);
5202           }
5203
5204         } else {
5205           if(lit == 1) {
5206             genSkipz2(&rFalseIfx,1);
5207           } else {
5208             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5209             genSkipc(&rFalseIfx);
5210           }
5211         }
5212
5213         if(ifx) ifx->generated = 1;
5214         return;
5215       }
5216
5217       /* chars are out of the way. now do ints and longs */
5218
5219
5220       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5221         
5222       /* special cases */
5223
5224       if(sign) {
5225
5226         if(lit == 0) {
5227           genSkipCond(&rFalseIfx,left,size,7);
5228           if(ifx) ifx->generated = 1;
5229           return;
5230         }
5231
5232         if(lit <0x100) {
5233           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5234
5235           //rFalseIfx.condition ^= 1;
5236           //genSkipCond(&rFalseIfx,left,size,7);
5237           //rFalseIfx.condition ^= 1;
5238
5239           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5240           if(rFalseIfx.condition)
5241             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5242           else
5243             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5244
5245           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5246           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5247           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5248
5249           while(size > 1)
5250             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5251
5252           if(rFalseIfx.condition) {
5253             emitSKPZ;
5254             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5255
5256           } else {
5257             emitSKPNZ;
5258           }
5259
5260           genSkipc(&rFalseIfx);
5261           pic16_emitpLabel(truelbl->key);
5262           if(ifx) ifx->generated = 1;
5263           return;
5264
5265         }
5266
5267         if(size == 1) {
5268
5269           if( (lit & 0xff) == 0) {
5270             /* lower byte is zero */
5271             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5272             i = ((lit >> 8) & 0xff) ^0x80;
5273             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5274             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5275             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5276             genSkipc(&rFalseIfx);
5277
5278
5279             if(ifx) ifx->generated = 1;
5280             return;
5281
5282           }
5283         } else {
5284           /* Special cases for signed longs */
5285           if( (lit & 0xffffff) == 0) {
5286             /* lower byte is zero */
5287             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5288             i = ((lit >> 8*3) & 0xff) ^0x80;
5289             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5290             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5291             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5292             genSkipc(&rFalseIfx);
5293
5294
5295             if(ifx) ifx->generated = 1;
5296             return;
5297
5298           }
5299
5300         }
5301
5302
5303         if(lit & (0x80 << (size*8))) {
5304           /* lit is negative */
5305           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5306
5307           //genSkipCond(&rFalseIfx,left,size,7);
5308
5309           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5310
5311           if(rFalseIfx.condition)
5312             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5313           else
5314             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5315
5316
5317         } else {
5318           /* lit is positive */
5319           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5320           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5321           if(rFalseIfx.condition)
5322             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5323           else
5324             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5325
5326         }
5327
5328         /*
5329           This works, but is only good for ints.
5330           It also requires a "known zero" register.
5331           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5332           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5333           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5334           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5335           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5336           genSkipc(&rFalseIfx);
5337
5338           pic16_emitpLabel(truelbl->key);
5339           if(ifx) ifx->generated = 1;
5340           return;
5341         **/
5342           
5343         /* There are no more special cases, so perform a general compare */
5344   
5345         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5346         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5347
5348         while(size--) {
5349
5350           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5351           emitSKPNZ;
5352           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5353         }
5354         //rFalseIfx.condition ^= 1;
5355         genSkipc(&rFalseIfx);
5356
5357         pic16_emitpLabel(truelbl->key);
5358
5359         if(ifx) ifx->generated = 1;
5360         return;
5361
5362
5363       }
5364
5365
5366       /* sign is out of the way. So now do an unsigned compare */
5367       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5368
5369
5370       /* General case - compare to an unsigned literal on the right.*/
5371
5372       i = (lit >> (size*8)) & 0xff;
5373       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5374       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5375       while(size--) {
5376         i = (lit >> (size*8)) & 0xff;
5377
5378         if(i) {
5379           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5380           emitSKPNZ;
5381           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5382         } else {
5383           /* this byte of the lit is zero, 
5384            *if it's not the last then OR in the variable */
5385           if(size)
5386             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5387         }
5388       }
5389
5390
5391       pic16_emitpLabel(lbl->key);
5392 //      pic16_emitpLabel(truelbl->key);
5393       //if(emitFinalCheck)
5394       genSkipc(&rFalseIfx);
5395       if(sign)
5396         pic16_emitpLabel(truelbl->key);
5397
5398       if(ifx) ifx->generated = 1;
5399       return;
5400
5401
5402     }
5403 #endif  // _swapp
5404
5405     if(AOP_TYPE(left) == AOP_LIT) {
5406       //symbol *lbl = newiTempLabel(NULL);
5407
5408       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5409
5410
5411       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5412
5413       /* Special cases */
5414       if((lit == 0) && (sign == 0)){
5415
5416         size--;
5417         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5418         while(size) 
5419           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5420
5421         genSkipz2(&rFalseIfx,0);
5422         if(ifx) ifx->generated = 1;
5423         return;
5424       }
5425
5426       if(size==1) {
5427         /* Special cases */
5428         lit &= 0xff;
5429         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5430           /* degenerate compare can never be true */
5431           if(rFalseIfx.condition == 0)
5432             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5433
5434           if(ifx) ifx->generated = 1;
5435           return;
5436         }
5437
5438         if(sign) {
5439           /* signed comparisons to a literal byte */
5440
5441           int lp1 = (lit+1) & 0xff;
5442
5443           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5444           switch (lp1) {
5445           case 0:
5446             rFalseIfx.condition ^= 1;
5447             genSkipCond(&rFalseIfx,right,0,7);
5448             break;
5449           case 0x7f:
5450             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5451             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5452             genSkipz2(&rFalseIfx,1);
5453             break;
5454           default:
5455             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5456             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5457             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5458             rFalseIfx.condition ^= 1;
5459             genSkipc(&rFalseIfx);
5460             break;
5461           }
5462         } else {
5463           /* unsigned comparisons to a literal byte */
5464
5465           switch(lit & 0xff ) {
5466           case 0:
5467             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5468             genSkipz2(&rFalseIfx,0);
5469             break;
5470           case 0x7f:
5471             rFalseIfx.condition ^= 1;
5472             genSkipCond(&rFalseIfx,right,0,7);
5473             break;
5474
5475           default:
5476             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5477             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5478             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5479             rFalseIfx.condition ^= 1;
5480             if (AOP_TYPE(result) == AOP_CRY)
5481               genSkipc(&rFalseIfx);
5482             else {
5483               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5484               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5485             }         
5486             break;
5487           }
5488         }
5489
5490         if(ifx) ifx->generated = 1;
5491         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5492                 goto check_carry;
5493         return;
5494
5495       } else {
5496
5497         /* Size is greater than 1 */
5498
5499         if(sign) {
5500           int lp1 = lit+1;
5501
5502           size--;
5503
5504           if(lp1 == 0) {
5505             /* this means lit = 0xffffffff, or -1 */
5506
5507
5508             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5509             rFalseIfx.condition ^= 1;
5510             genSkipCond(&rFalseIfx,right,size,7);
5511             if(ifx) ifx->generated = 1;
5512
5513             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5514               goto check_carry;
5515
5516             return;
5517           }
5518
5519           if(lit == 0) {
5520             int s = size;
5521
5522             if(rFalseIfx.condition) {
5523               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5524               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5525             }
5526
5527             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5528             while(size--)
5529               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5530
5531
5532             emitSKPZ;
5533             if(rFalseIfx.condition) {
5534               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5535               pic16_emitpLabel(truelbl->key);
5536             }else {
5537               rFalseIfx.condition ^= 1;
5538               genSkipCond(&rFalseIfx,right,s,7);
5539             }
5540
5541             if(ifx) ifx->generated = 1;
5542
5543             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5544               goto check_carry;
5545
5546             return;
5547           }
5548
5549           if((size == 1) &&  (0 == (lp1&0xff))) {
5550             /* lower byte of signed word is zero */
5551             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5552             i = ((lp1 >> 8) & 0xff) ^0x80;
5553             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5554             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5555             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5556
5557             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5558               emitTOGC;
5559               if(ifx) ifx->generated = 1;
5560               goto check_carry;
5561             } else {
5562               rFalseIfx.condition ^= 1;
5563               genSkipc(&rFalseIfx);
5564               if(ifx) ifx->generated = 1;
5565             }
5566
5567             return;
5568           }
5569
5570           if(lit & (0x80 << (size*8))) {
5571             /* Lit is less than zero */
5572             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5573             //rFalseIfx.condition ^= 1;
5574             //genSkipCond(&rFalseIfx,left,size,7);
5575             //rFalseIfx.condition ^= 1;
5576             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5577             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5578
5579             if(rFalseIfx.condition)
5580               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5581             else
5582               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5583
5584
5585           } else {
5586             /* Lit is greater than or equal to zero */
5587             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5588             //rFalseIfx.condition ^= 1;
5589             //genSkipCond(&rFalseIfx,right,size,7);
5590             //rFalseIfx.condition ^= 1;
5591
5592             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5593             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5594
5595             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5596             if(rFalseIfx.condition)
5597               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5598             else
5599               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5600
5601           }
5602
5603           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5604           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5605
5606           while(size--) {
5607
5608             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5609             emitSKPNZ;
5610             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5611           }
5612           rFalseIfx.condition ^= 1;
5613           //rFalseIfx.condition = 1;
5614           genSkipc(&rFalseIfx);
5615
5616           pic16_emitpLabel(truelbl->key);
5617
5618           if(ifx) ifx->generated = 1;
5619
5620
5621           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5622             goto check_carry;
5623
5624           return;
5625           // end of if (sign)
5626         } else {
5627
5628           /* compare word or long to an unsigned literal on the right.*/
5629
5630
5631           size--;
5632           if(lit < 0xff) {
5633             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5634             switch (lit) {
5635             case 0:
5636               break; /* handled above */
5637 /*
5638             case 0xff:
5639               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5640               while(size--)
5641                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5642               genSkipz2(&rFalseIfx,0);
5643               break;
5644 */
5645             default:
5646               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5647               while(--size)
5648                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5649
5650               emitSKPZ;
5651               if(rFalseIfx.condition)
5652                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5653               else
5654                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5655
5656
5657               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5658               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5659
5660               rFalseIfx.condition ^= 1;
5661               genSkipc(&rFalseIfx);
5662             }
5663
5664             pic16_emitpLabel(truelbl->key);
5665
5666             if(ifx) ifx->generated = 1;
5667
5668             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5669               goto check_carry;
5670
5671             return;
5672           }
5673
5674
5675           lit++;
5676           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5677           i = (lit >> (size*8)) & 0xff;
5678
5679           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5680           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5681
5682           while(size--) {
5683             i = (lit >> (size*8)) & 0xff;
5684
5685             if(i) {
5686               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5687               emitSKPNZ;
5688               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5689             } else {
5690               /* this byte of the lit is zero, 
5691                * if it's not the last then OR in the variable */
5692               if(size)
5693                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5694             }
5695           }
5696
5697
5698           pic16_emitpLabel(lbl->key);
5699
5700           rFalseIfx.condition ^= 1;
5701
5702           genSkipc(&rFalseIfx);
5703         }
5704
5705         if(sign)
5706           pic16_emitpLabel(truelbl->key);
5707         if(ifx) ifx->generated = 1;
5708
5709             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5710               goto check_carry;
5711
5712         return;
5713       }
5714     }
5715     /* Compare two variables */
5716
5717     DEBUGpic16_emitcode(";sign","%d",sign);
5718
5719     size--;
5720     if(sign) {
5721       /* Sigh. thus sucks... */
5722       if(size) {
5723         pCodeOp *pctemp;
5724         
5725         pctemp = pic16_popGetTempReg(1);
5726         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5727         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5728         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5729         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5730         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5731         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5732         pic16_popReleaseTempReg(pctemp, 1);
5733       } else {
5734         /* Signed char comparison */
5735         /* Special thanks to Nikolai Golovchenko for this snippet */
5736         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5737         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5738         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5739         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5740         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5741         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5742
5743         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5744         genSkipc(&rFalseIfx);
5745           
5746         if(ifx) ifx->generated = 1;
5747
5748             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5749               goto check_carry;
5750
5751         return;
5752       }
5753
5754     } else {
5755
5756       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5757       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5758     }
5759
5760
5761     /* The rest of the bytes of a multi-byte compare */
5762     while (size) {
5763
5764       emitSKPZ;
5765       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5766       size--;
5767
5768       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5769       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5770
5771
5772     }
5773
5774     pic16_emitpLabel(lbl->key);
5775
5776     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5777     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5778         (AOP_TYPE(result) == AOP_REG)) {
5779       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5780       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5781     } else {
5782       genSkipc(&rFalseIfx);
5783     }         
5784     //genSkipc(&rFalseIfx);
5785     if(ifx) ifx->generated = 1;
5786
5787
5788             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5789               goto check_carry;
5790
5791     return;
5792
5793   }
5794
5795 check_carry:
5796   if ((AOP_TYPE(result) != AOP_CRY) 
5797         && AOP_SIZE(result)) {
5798     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5799
5800     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5801
5802     pic16_outBitC(result);
5803   } else {
5804     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5805     /* if the result is used in the next
5806        ifx conditional branch then generate
5807        code a little differently */
5808     if (ifx )
5809       genIfxJump (ifx,"c");
5810     else
5811       pic16_outBitC(result);
5812     /* leave the result in acc */
5813   }
5814
5815 }
5816
5817 #elif 0 /* VR version of genCmp() */    /* } else { */
5818
5819 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5820 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5821         operand *result, int offset, int invert_op)
5822 {
5823   /* add code here */
5824   
5825   /* check condition, > or < ?? */
5826   if(rIfx->condition != 0)invert_op ^= 1;
5827   
5828   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5829
5830   if(!ifx)invert_op ^= 1;
5831
5832   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5833       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5834   
5835   /* do selection */
5836   if(!invert_op)return POC_CPFSGT;
5837   else return POC_CPFSLT;
5838 }
5839
5840 static int compareAopfirstpass=1;
5841
5842 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5843             operand *oper, int offset, operand *result,
5844             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5845             symbol *tlbl)
5846 {
5847   int op;
5848   symbol *truelbl;
5849
5850   /* invert if there is a result to be loaded, in order to fit,
5851    * SETC/CLRC sequence */
5852   if(AOP_SIZE(result))invert_op ^= 1;
5853
5854 //  if(sign && !offset)invert_op ^= 1;
5855   
5856 //  if(sign)invert_op ^= 1;
5857   
5858   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5859
5860   if(AOP_SIZE(result) && compareAopfirstpass) {
5861     if(!ifx) {
5862       if(pcop2)
5863         pic16_emitpcode(POC_SETF, pcop2);
5864       else
5865         emitSETC;
5866     } else {
5867       if(pcop2)
5868         pic16_emitpcode(POC_CLRF, pcop2);
5869       else
5870         emitCLRC;
5871     }
5872   }
5873
5874   compareAopfirstpass = 0;
5875
5876       /* there is a bug when comparing operands with size > 1,
5877        * because higher bytes can be equal and test should be performed
5878        * to the next lower byte, current algorithm, considers operands
5879        * inequal in these cases! -- VR 20041107 */
5880
5881     
5882   if(pcop)
5883     pic16_emitpcode(op, pcop);
5884   else
5885     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5886
5887
5888   if((!sign || !offset) && AOP_SIZE(result)) {
5889     if(!ifx) {
5890       if(pcop2)
5891         pic16_emitpcode(POC_CLRF, pcop2);
5892         else
5893         emitCLRC;
5894     } else {
5895       if(pcop2)
5896         pic16_emitpcode(POC_SETF, pcop2);
5897       else
5898         emitSETC;
5899     }
5900     
5901     /* don't emit final branch (offset == 0) */
5902     if(offset) {
5903
5904       if(pcop2)
5905         pic16_emitpcode(POC_RRCF, pcop2);
5906
5907       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5908     }
5909   } else {
5910     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5911       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5912             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5913
5914       truelbl = newiTempLabel( NULL );
5915       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5916       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5917         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5918       else
5919         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5920       pic16_emitpLabel(truelbl->key);
5921     } else {
5922       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5923     }
5924   }
5925 }
5926
5927 static void genCmp (operand *left, operand *right,
5928                     operand *result, iCode *ifx, int sign)
5929 {
5930   int size, cmpop=1;
5931   long lit = 0L;
5932   resolvedIfx rFalseIfx;
5933   symbol *falselbl, *tlbl;
5934
5935     FENTRY;
5936     
5937     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5938
5939     resolveIfx(&rFalseIfx, ifx);
5940     size = max(AOP_SIZE(left), AOP_SIZE(right));
5941     
5942     /* if left & right are bit variables */
5943     if(AOP_TYPE(left) == AOP_CRY
5944       && AOP_TYPE(right) == AOP_CRY ) {
5945
5946         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5947         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5948         
5949         werror(W_POSSBUG2, __FILE__, __LINE__);
5950         exit(-1);
5951     }
5952     
5953     /* if literal is on the right then swap with left */
5954     if((AOP_TYPE(right) == AOP_LIT)) {
5955       operand *tmp = right ;
5956 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5957
5958         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5959
5960 //      lit = (lit - 1) & mask;
5961         right = left;
5962         left = tmp;
5963         rFalseIfx.condition ^= 1;               /* reverse compare */
5964     } else
5965     if ((AOP_TYPE(left) == AOP_LIT)) {
5966       /* float compares are handled by support functions */
5967       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5968     }
5969
5970     /* actual comparing algorithm */
5971 //    size = AOP_SIZE( right );
5972
5973     falselbl = newiTempLabel( NULL );
5974     if(AOP_TYPE(left) == AOP_LIT) {
5975       /* compare to literal */
5976       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5977       
5978       if(sign) {
5979         pCodeOp *pct, *pct2;
5980         symbol *tlbl1;
5981
5982         /* signed compare */
5983         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5984
5985         pct = pic16_popCopyReg(&pic16_pc_prodl);
5986         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5987         tlbl = newiTempLabel( NULL );
5988         
5989         /* first compare signs:
5990          *  a. if both are positive, compare just like unsigned
5991          *  b. if both are negative, invert cmpop, compare just like unsigned
5992          *  c. if different signs, determine the result directly */
5993
5994         size--;
5995
5996 #if 1
5997         /* { */
5998         tlbl1 = newiTempLabel( NULL );
5999 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6000
6001         if(lit > 0) {
6002
6003           /* literal is zero or positive:
6004            *  a. if carry is zero, too, continue compare,
6005            *  b. if carry is set, then continue depending on cmpop ^ condition:
6006            *    1. '<' return false (literal < variable),
6007            *    2. '>' return true (literal > variable) */
6008 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6009           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6010           
6011           
6012           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6013           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6014         } else 
6015         if(lit < 0) {
6016           
6017           /* literal is negative:
6018            *  a. if carry is set, too, continue compare,
6019            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6020            *    1. '<' return true (literal < variable),
6021            *    2. '>' return false (literal > variable) */
6022 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6023           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6024           
6025           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6026           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6027         }
6028 #if 1
6029         else {
6030           /* lit == 0 */
6031           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6032           
6033           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6034           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6035         }
6036 #endif
6037         
6038         
6039         pic16_emitpLabel( tlbl1->key );
6040 #endif  /* } */
6041
6042         compareAopfirstpass=1;
6043 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6044 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6045 //        pic16_emitpcode(POC_MOVWF, pct);
6046
6047 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6048         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6049 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6050         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6051
6052         /* generic case */        
6053           while( size-- ) {
6054 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6055 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6056 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6057 //            pic16_emitpcode(POC_MOVWF, pct);
6058
6059 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6060             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6061             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6062 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6063 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6064           }
6065         
6066         if(ifx)ifx->generated = 1;
6067
6068         if(AOP_SIZE(result)) {
6069           pic16_emitpLabel(tlbl->key);
6070           pic16_emitpLabel(falselbl->key);
6071           pic16_outBitOp( result, pct2 );
6072         } else {
6073           pic16_emitpLabel(tlbl->key);
6074         }
6075       } else {
6076
6077         /* unsigned compare */      
6078         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6079     
6080         compareAopfirstpass=1;
6081         while(size--) {
6082           
6083           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6084           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6085
6086         }
6087         if(ifx)ifx->generated = 1;
6088
6089         if(AOP_SIZE(result)) {
6090           pic16_emitpLabel(falselbl->key);
6091           pic16_outBitC( result );
6092         }
6093
6094       }
6095     } else {
6096       /* compare registers */
6097       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6098
6099
6100       if(sign) {
6101         pCodeOp *pct, *pct2;
6102         
6103         /* signed compare */
6104         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6105
6106         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6107         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6108         tlbl = newiTempLabel( NULL );
6109         
6110         compareAopfirstpass=1;
6111
6112         size--;
6113         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6114 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6115         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6116         pic16_emitpcode(POC_MOVWF, pct);
6117
6118         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6119 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6120         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6121
6122         /* WREG already holds left + 0x80 */
6123         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6124         
6125         while( size-- ) {
6126           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6127 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6128           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6129           pic16_emitpcode(POC_MOVWF, pct);
6130                 
6131           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6132 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6133           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6134
6135           /* WREG already holds left + 0x80 */
6136           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6137 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6138         }
6139         
6140         if(ifx)ifx->generated = 1;
6141
6142         if(AOP_SIZE(result)) {
6143           pic16_emitpLabel(tlbl->key);
6144           pic16_emitpLabel(falselbl->key);
6145           pic16_outBitOp( result, pct2 );
6146         } else {
6147           pic16_emitpLabel(tlbl->key);
6148         }
6149
6150       } else {
6151         /* unsigned compare */      
6152         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6153
6154         compareAopfirstpass=1;
6155         while(size--) {
6156           
6157           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6158           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6159
6160         }
6161
6162         if(ifx)ifx->generated = 1;
6163         if(AOP_SIZE(result)) {
6164
6165           pic16_emitpLabel(falselbl->key);
6166           pic16_outBitC( result );
6167         }
6168
6169       }
6170     }
6171 }
6172
6173 #endif  /* } */
6174
6175
6176
6177 /*-----------------------------------------------------------------*/
6178 /* genCmpGt :- greater than comparison                             */
6179 /*-----------------------------------------------------------------*/
6180 static void genCmpGt (iCode *ic, iCode *ifx)
6181 {
6182   operand *left, *right, *result;
6183   sym_link *letype , *retype;
6184   int sign ;
6185
6186     FENTRY;
6187     
6188     left = IC_LEFT(ic);
6189     right= IC_RIGHT(ic);
6190     result = IC_RESULT(ic);
6191
6192     letype = getSpec(operandType(left));
6193     retype =getSpec(operandType(right));
6194     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6195     /* assign the amsops */
6196     pic16_aopOp (left,ic,FALSE);
6197     pic16_aopOp (right,ic,FALSE);
6198     pic16_aopOp (result,ic,TRUE);
6199
6200     genCmp(right, left, result, ifx, sign);
6201
6202     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6203     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6204     pic16_freeAsmop(result,NULL,ic,TRUE); 
6205 }
6206
6207 /*-----------------------------------------------------------------*/
6208 /* genCmpLt - less than comparisons                                */
6209 /*-----------------------------------------------------------------*/
6210 static void genCmpLt (iCode *ic, iCode *ifx)
6211 {
6212   operand *left, *right, *result;
6213   sym_link *letype , *retype;
6214   int sign ;
6215
6216     FENTRY;
6217
6218     left = IC_LEFT(ic);
6219     right= IC_RIGHT(ic);
6220     result = IC_RESULT(ic);
6221
6222     letype = getSpec(operandType(left));
6223     retype =getSpec(operandType(right));
6224     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6225
6226     /* assign the amsops */
6227     pic16_aopOp (left,ic,FALSE);
6228     pic16_aopOp (right,ic,FALSE);
6229     pic16_aopOp (result,ic,TRUE);
6230
6231     genCmp(left, right, result, ifx, sign);
6232
6233     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6234     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6235     pic16_freeAsmop(result,NULL,ic,TRUE); 
6236 }
6237
6238 #if 0
6239 // not needed ATM
6240 // FIXME reenable literal optimisation when the pic16 port is stable
6241
6242 /*-----------------------------------------------------------------*/
6243 /* genc16bit2lit - compare a 16 bit value to a literal             */
6244 /*-----------------------------------------------------------------*/
6245 static void genc16bit2lit(operand *op, int lit, int offset)
6246 {
6247   int i;
6248
6249   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6250   if( (lit&0xff) == 0) 
6251     i=1;
6252   else
6253     i=0;
6254
6255   switch( BYTEofLONG(lit,i)) { 
6256   case 0:
6257     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6258     break;
6259   case 1:
6260     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6261     break;
6262   case 0xff:
6263     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6264     break;
6265   default:
6266     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6267     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6268   }
6269
6270   i ^= 1;
6271
6272   switch( BYTEofLONG(lit,i)) { 
6273   case 0:
6274     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6275     break;
6276   case 1:
6277     emitSKPNZ;
6278     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6279     break;
6280   case 0xff:
6281     emitSKPNZ;
6282     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6283     break;
6284   default:
6285     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6286     emitSKPNZ;
6287     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6288
6289   }
6290
6291 }
6292 #endif
6293
6294 #if 0
6295 // not needed ATM
6296 /*-----------------------------------------------------------------*/
6297 /* gencjneshort - compare and jump if not equal                    */
6298 /*-----------------------------------------------------------------*/
6299 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6300 {
6301   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6302   int offset = 0;
6303   int res_offset = 0;  /* the result may be a different size then left or right */
6304   int res_size = AOP_SIZE(result);
6305   resolvedIfx rIfx;
6306   symbol *lbl, *lbl_done;
6307
6308   unsigned long lit = 0L;
6309   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6310
6311   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6312   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6313   if(result)
6314     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6315   resolveIfx(&rIfx,ifx);
6316   lbl =  newiTempLabel(NULL);
6317   lbl_done =  newiTempLabel(NULL);
6318
6319
6320   /* if the left side is a literal or 
6321      if the right is in a pointer register and left 
6322      is not */
6323   if ((AOP_TYPE(left) == AOP_LIT) || 
6324       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6325     operand *t = right;
6326     right = left;
6327     left = t;
6328   }
6329   if(AOP_TYPE(right) == AOP_LIT)
6330     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6331
6332   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6333     preserve_result = 1;
6334
6335   if(result && !preserve_result)
6336     {
6337       int i;
6338       for(i = 0; i < AOP_SIZE(result); i++)
6339         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6340     }
6341
6342
6343   /* if the right side is a literal then anything goes */
6344   if (AOP_TYPE(right) == AOP_LIT &&
6345       AOP_TYPE(left) != AOP_DIR ) {
6346     switch(size) {
6347     case 2:
6348       genc16bit2lit(left, lit, 0);
6349       emitSKPZ;
6350       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6351       break;
6352     default:
6353       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6354       while (size--) {
6355         if(lit & 0xff) {
6356           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6357           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6358         } else {
6359           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6360         }
6361
6362         emitSKPZ;
6363         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6364         offset++;
6365         if(res_offset < res_size-1)
6366           res_offset++;
6367         lit >>= 8;
6368       }
6369       break;
6370     }
6371   }
6372
6373   /* if the right side is in a register or in direct space or
6374      if the left is a pointer register & right is not */    
6375   else if (AOP_TYPE(right) == AOP_REG ||
6376            AOP_TYPE(right) == AOP_DIR || 
6377            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6378            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6379     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6380     int lbl_key = lbl->key;
6381
6382     if(result) {
6383       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6384       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6385     }else {
6386       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6387       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6388               __FUNCTION__,__LINE__);
6389       return;
6390     }
6391    
6392 /*     switch(size) { */
6393 /*     case 2: */
6394 /*       genc16bit2lit(left, lit, 0); */
6395 /*       emitSKPNZ; */
6396 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6397 /*       break; */
6398 /*     default: */
6399     while (size--) {
6400       int emit_skip=1;
6401       if((AOP_TYPE(left) == AOP_DIR) && 
6402          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6403
6404         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6405         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6406
6407       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6408             
6409         switch (lit & 0xff) {
6410         case 0:
6411           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6412           break;
6413         case 1:
6414           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6415           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6416           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6417           emit_skip=0;
6418           break;
6419         case 0xff:
6420           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6421           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6422           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6423           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6424           emit_skip=0;
6425           break;
6426         default:
6427           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6428           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6429         }
6430         lit >>= 8;
6431
6432       } else {
6433         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6434       }
6435       if(emit_skip) {
6436         if(AOP_TYPE(result) == AOP_CRY) {
6437           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6438           if(rIfx.condition)
6439             emitSKPNZ;
6440           else
6441             emitSKPZ;
6442           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6443         } else {
6444           /* fix me. probably need to check result size too */
6445           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6446           if(rIfx.condition)
6447             emitSKPZ;
6448           else
6449             emitSKPNZ;
6450           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6451           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6452         }
6453         if(ifx)
6454           ifx->generated=1;
6455       }
6456       emit_skip++;
6457       offset++;
6458       if(res_offset < res_size-1)
6459         res_offset++;
6460     }
6461 /*       break; */
6462 /*     } */
6463   } else if(AOP_TYPE(right) == AOP_REG &&
6464             AOP_TYPE(left) != AOP_DIR){
6465
6466     while(size--) {
6467       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6468       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6469       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6470       if(rIfx.condition)
6471         emitSKPNZ;
6472       else
6473         emitSKPZ;
6474       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6475       offset++;
6476       if(res_offset < res_size-1)
6477         res_offset++;
6478     }
6479       
6480   }else{
6481     /* right is a pointer reg need both a & b */
6482     while(size--) {
6483       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6484       if(strcmp(l,"b"))
6485         pic16_emitcode("mov","b,%s",l);
6486       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6487       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6488       offset++;
6489     }
6490   }
6491
6492   if(result && preserve_result)
6493     {
6494       int i;
6495       for(i = 0; i < AOP_SIZE(result); i++)
6496         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6497     }
6498
6499   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6500
6501   if(result && preserve_result)
6502     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6503
6504   if(!rIfx.condition)
6505     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6506
6507   pic16_emitpLabel(lbl->key);
6508
6509   if(result && preserve_result)
6510     {
6511       int i;
6512       for(i = 0; i < AOP_SIZE(result); i++)
6513         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6514
6515       pic16_emitpLabel(lbl_done->key);
6516    }
6517
6518   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6519
6520   if(ifx)
6521     ifx->generated = 1;
6522 }
6523 #endif
6524
6525 #if 0
6526 /*-----------------------------------------------------------------*/
6527 /* gencjne - compare and jump if not equal                         */
6528 /*-----------------------------------------------------------------*/
6529 static void gencjne(operand *left, operand *right, iCode *ifx)
6530 {
6531     symbol *tlbl  = newiTempLabel(NULL);
6532
6533     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6534     gencjneshort(left, right, lbl);
6535
6536     pic16_emitcode("mov","a,%s",one);
6537     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6538     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6539     pic16_emitcode("clr","a");
6540     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6541
6542     pic16_emitpLabel(lbl->key);
6543     pic16_emitpLabel(tlbl->key);
6544
6545 }
6546 #endif
6547
6548
6549 /*-----------------------------------------------------------------*/
6550 /* is_LitOp - check if operand has to be treated as literal        */
6551 /*-----------------------------------------------------------------*/
6552 static bool is_LitOp(operand *op)
6553 {
6554   return ((AOP_TYPE(op) == AOP_LIT)
6555       || ( (AOP_TYPE(op) == AOP_PCODE)
6556           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6557               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6558 }
6559
6560 /*-----------------------------------------------------------------*/
6561 /* is_LitAOp - check if operand has to be treated as literal        */
6562 /*-----------------------------------------------------------------*/
6563 static bool is_LitAOp(asmop *aop)
6564 {
6565   return ((aop->type == AOP_LIT)
6566       || ( (aop->type == AOP_PCODE)
6567           && ( (aop->aopu.pcop->type == PO_LITERAL)
6568               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6569 }
6570
6571
6572
6573 /*-----------------------------------------------------------------*/
6574 /* genCmpEq - generates code for equal to                          */
6575 /*-----------------------------------------------------------------*/
6576 static void genCmpEq (iCode *ic, iCode *ifx)
6577 {
6578   operand *left, *right, *result;
6579   symbol *falselbl = newiTempLabel(NULL);
6580   symbol *donelbl = newiTempLabel(NULL);
6581
6582   int preserve_result = 0;
6583   int generate_result = 0;
6584   int i=0;
6585   unsigned long lit = -1;
6586
6587   FENTRY;
6588   
6589   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6590   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6591   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6592  
6593   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6594
6595   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6596     {
6597       werror(W_POSSBUG2, __FILE__, __LINE__);
6598       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6599       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6600       goto release;
6601     }
6602
6603   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6604     {
6605       operand *tmp = right ;
6606       right = left;
6607       left = tmp;
6608     }
6609
6610   if (AOP_TYPE(right) == AOP_LIT) {
6611     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6612   }
6613
6614   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6615     preserve_result = 1;
6616
6617   if(result && AOP_SIZE(result))
6618     generate_result = 1;
6619
6620   if(generate_result && !preserve_result)
6621     {
6622       for(i = 0; i < AOP_SIZE(result); i++)
6623         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6624     }
6625
6626   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6627   for(i=0; i < AOP_SIZE(left); i++)
6628     {
6629       if(AOP_TYPE(left) != AOP_ACC)
6630         {
6631           if(is_LitOp(left))
6632             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6633           else
6634             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6635         }
6636       if(is_LitOp(right)) {
6637         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6638           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6639         }
6640       } else
6641         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6642
6643       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6644     }
6645
6646   // result == true
6647
6648   if(generate_result && preserve_result)
6649     {
6650       for(i = 0; i < AOP_SIZE(result); i++)
6651         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6652     }
6653
6654   if(generate_result)
6655     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6656
6657   if(generate_result && preserve_result)
6658     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6659
6660   if(ifx && IC_TRUE(ifx))
6661     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6662
6663   if(ifx && IC_FALSE(ifx))
6664     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6665
6666   pic16_emitpLabel(falselbl->key);
6667
6668   // result == false
6669
6670   if(ifx && IC_FALSE(ifx))
6671     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6672
6673   if(generate_result && preserve_result)
6674     {
6675       for(i = 0; i < AOP_SIZE(result); i++)
6676         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6677     }
6678
6679   pic16_emitpLabel(donelbl->key);
6680
6681   if(ifx)
6682     ifx->generated = 1;
6683
6684 release:
6685   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6686   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6687   pic16_freeAsmop(result,NULL,ic,TRUE);
6688
6689 }
6690
6691
6692 #if 0
6693 // old version kept for reference
6694
6695 /*-----------------------------------------------------------------*/
6696 /* genCmpEq - generates code for equal to                          */
6697 /*-----------------------------------------------------------------*/
6698 static void genCmpEq (iCode *ic, iCode *ifx)
6699 {
6700     operand *left, *right, *result;
6701     unsigned long lit = 0L;
6702     int size,offset=0;
6703     symbol *falselbl  = newiTempLabel(NULL);
6704
6705
6706     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6707
6708     if(ifx)
6709       DEBUGpic16_emitcode ("; ifx is non-null","");
6710     else
6711       DEBUGpic16_emitcode ("; ifx is null","");
6712
6713     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6714     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6715     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6716
6717     size = max(AOP_SIZE(left),AOP_SIZE(right));
6718
6719     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6720
6721     /* if literal, literal on the right or 
6722     if the right is in a pointer register and left 
6723     is not */
6724     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6725         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6726       operand *tmp = right ;
6727       right = left;
6728       left = tmp;
6729     }
6730
6731
6732     if(ifx && !AOP_SIZE(result)){
6733         symbol *tlbl;
6734         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6735         /* if they are both bit variables */
6736         if (AOP_TYPE(left) == AOP_CRY &&
6737             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6738                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6739             if(AOP_TYPE(right) == AOP_LIT){
6740                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6741                 if(lit == 0L){
6742                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6743                     pic16_emitcode("cpl","c");
6744                 } else if(lit == 1L) {
6745                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6746                 } else {
6747                     pic16_emitcode("clr","c");
6748                 }
6749                 /* AOP_TYPE(right) == AOP_CRY */
6750             } else {
6751                 symbol *lbl = newiTempLabel(NULL);
6752                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6753                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6754                 pic16_emitcode("cpl","c");
6755                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6756             }
6757             /* if true label then we jump if condition
6758             supplied is true */
6759             tlbl = newiTempLabel(NULL);
6760             if ( IC_TRUE(ifx) ) {
6761                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6762                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6763             } else {
6764                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6765                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6766             }
6767             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6768
6769                 {
6770                 /* left and right are both bit variables, result is carry */
6771                         resolvedIfx rIfx;
6772               
6773                         resolveIfx(&rIfx,ifx);
6774
6775                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6776                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6777                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6778                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6779                         genSkipz2(&rIfx,0);
6780                 }
6781         } else {
6782
6783                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6784
6785                         /* They're not both bit variables. Is the right a literal? */
6786                         if(AOP_TYPE(right) == AOP_LIT) {
6787                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6788             
6789                         switch(size) {
6790
6791                                 case 1:
6792                                         switch(lit & 0xff) {
6793                                                 case 1:
6794                                                                 if ( IC_TRUE(ifx) ) {
6795                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6796                                                                         emitSKPNZ;
6797                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6798                                                                 } else {
6799                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6800                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6801                                                                 }
6802                                                                 break;
6803                                                 case 0xff:
6804                                                                 if ( IC_TRUE(ifx) ) {
6805                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6806                                                                         emitSKPNZ;
6807                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6808                                                                 } else {
6809                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6810                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6811                                                                 }
6812                                                                 break;
6813                                                 default:
6814                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6815                                                                 if(lit)
6816                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6817                                                                 genSkip(ifx,'z');
6818                                         } // switch lit
6819
6820
6821                                         /* end of size == 1 */
6822                                         break;
6823               
6824                                 case 2:
6825                                         genc16bit2lit(left,lit,offset);
6826                                         genSkip(ifx,'z');
6827                                         break;
6828                                         /* end of size == 2 */
6829
6830                                 default:
6831                                         /* size is 4 */
6832                                         if(lit==0) {
6833                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6834                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6835                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6836                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6837                                                 genSkip(ifx,'z');
6838                                         } else {
6839                                                 /* search for patterns that can be optimized */
6840
6841                                                 genc16bit2lit(left,lit,0);
6842                                                 lit >>= 16;
6843                                                 if(lit) {
6844                                                                 if(IC_TRUE(ifx))
6845                                                                 emitSKPZ; // if hi word unequal
6846                                                                 else
6847                                                                 emitSKPNZ; // if hi word equal
6848                                                                 // fail early
6849                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6850                                                         genc16bit2lit(left,lit,2);
6851                                                         genSkip(ifx,'z');
6852                                                 } else {
6853                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6854                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6855                                                         genSkip(ifx,'z');
6856                                                 }
6857                                         }
6858                                                 pic16_emitpLabel(falselbl->key);
6859                                                 break;
6860
6861                         } // switch size
6862           
6863                         ifx->generated = 1;
6864                         goto release ;
6865             
6866
6867           } else if(AOP_TYPE(right) == AOP_CRY ) {
6868             /* we know the left is not a bit, but that the right is */
6869             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6870             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6871                       pic16_popGet(AOP(right),offset));
6872             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6873
6874             /* if the two are equal, then W will be 0 and the Z bit is set
6875              * we could test Z now, or go ahead and check the high order bytes if
6876              * the variable we're comparing is larger than a byte. */
6877
6878             while(--size)
6879               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6880
6881             if ( IC_TRUE(ifx) ) {
6882               emitSKPNZ;
6883               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6884               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6885             } else {
6886               emitSKPZ;
6887               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6888               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6889             }
6890
6891           } else {
6892             /* They're both variables that are larger than bits */
6893             int s = size;
6894
6895             tlbl = newiTempLabel(NULL);
6896
6897             while(size--) {
6898               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6899               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6900
6901               if ( IC_TRUE(ifx) ) {
6902                 if(size) {
6903                   emitSKPZ;
6904                 
6905                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6906
6907                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6908                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6909                 } else {
6910                   emitSKPNZ;
6911
6912                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6913
6914
6915                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6916                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6917                 }
6918               } else {
6919                 emitSKPZ;
6920
6921                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6922
6923                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6924                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6925               }
6926               offset++;
6927             }
6928             if(s>1 && IC_TRUE(ifx)) {
6929               pic16_emitpLabel(tlbl->key);
6930               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6931             }
6932           }
6933         }
6934         /* mark the icode as generated */
6935         ifx->generated = 1;
6936         goto release ;
6937     }
6938
6939     /* if they are both bit variables */
6940     if (AOP_TYPE(left) == AOP_CRY &&
6941         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6942         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6943         if(AOP_TYPE(right) == AOP_LIT){
6944             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6945             if(lit == 0L){
6946                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6947                 pic16_emitcode("cpl","c");
6948             } else if(lit == 1L) {
6949                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6950             } else {
6951                 pic16_emitcode("clr","c");
6952             }
6953             /* AOP_TYPE(right) == AOP_CRY */
6954         } else {
6955             symbol *lbl = newiTempLabel(NULL);
6956             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6957             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6958             pic16_emitcode("cpl","c");
6959             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6960         }
6961         /* c = 1 if egal */
6962         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6963             pic16_outBitC(result);
6964             goto release ;
6965         }
6966         if (ifx) {
6967             genIfxJump (ifx,"c");
6968             goto release ;
6969         }
6970         /* if the result is used in an arithmetic operation
6971         then put the result in place */
6972         pic16_outBitC(result);
6973     } else {
6974       
6975       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6976       gencjne(left,right,result,ifx);
6977 /*
6978       if(ifx) 
6979         gencjne(left,right,newiTempLabel(NULL));
6980       else {
6981         if(IC_TRUE(ifx)->key)
6982           gencjne(left,right,IC_TRUE(ifx)->key);
6983         else
6984           gencjne(left,right,IC_FALSE(ifx)->key);
6985         ifx->generated = 1;
6986         goto release ;
6987       }
6988       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6989         pic16_aopPut(AOP(result),"a",0);
6990         goto release ;
6991       }
6992
6993       if (ifx) {
6994         genIfxJump (ifx,"a");
6995         goto release ;
6996       }
6997 */
6998       /* if the result is used in an arithmetic operation
6999          then put the result in place */
7000 /*
7001       if (AOP_TYPE(result) != AOP_CRY) 
7002         pic16_outAcc(result);
7003 */
7004       /* leave the result in acc */
7005     }
7006
7007 release:
7008     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7009     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7010     pic16_freeAsmop(result,NULL,ic,TRUE);
7011 }
7012 #endif
7013
7014 /*-----------------------------------------------------------------*/
7015 /* ifxForOp - returns the icode containing the ifx for operand     */
7016 /*-----------------------------------------------------------------*/
7017 static iCode *ifxForOp ( operand *op, iCode *ic )
7018 {
7019   FENTRY2;
7020
7021     /* if true symbol then needs to be assigned */
7022     if (IS_TRUE_SYMOP(op))
7023         return NULL ;
7024
7025     /* if this has register type condition and
7026     the next instruction is ifx with the same operand
7027     and live to of the operand is upto the ifx only then */
7028     if (ic->next
7029         && ic->next->op == IFX
7030         && IC_COND(ic->next)->key == op->key
7031         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7032         ) {
7033                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7034           return ic->next;
7035     }
7036
7037     /*
7038     if (ic->next &&
7039         ic->next->op == IFX &&
7040         IC_COND(ic->next)->key == op->key) {
7041       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7042       return ic->next;
7043     }
7044     */
7045
7046     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7047     if (ic->next &&
7048         ic->next->op == IFX)
7049       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7050
7051     if (ic->next &&
7052         ic->next->op == IFX &&
7053         IC_COND(ic->next)->key == op->key) {
7054       DEBUGpic16_emitcode ("; "," key is okay");
7055       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7056                            OP_SYMBOL(op)->liveTo,
7057                            ic->next->seq);
7058     }
7059
7060 #if 0
7061     /* the code below is completely untested
7062      * it just allows ulong2fs.c compile -- VR */
7063          
7064     ic = ic->next;
7065     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7066                                         __FILE__, __FUNCTION__, __LINE__);
7067         
7068     /* if this has register type condition and
7069     the next instruction is ifx with the same operand
7070     and live to of the operand is upto the ifx only then */
7071     if (ic->next &&
7072         ic->next->op == IFX &&
7073         IC_COND(ic->next)->key == op->key &&
7074         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7075         return ic->next;
7076
7077     if (ic->next &&
7078         ic->next->op == IFX &&
7079         IC_COND(ic->next)->key == op->key) {
7080       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7081       return ic->next;
7082     }
7083
7084     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7085                                         __FILE__, __FUNCTION__, __LINE__);
7086
7087 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7088 #endif
7089
7090     return NULL;
7091 }
7092 /*-----------------------------------------------------------------*/
7093 /* genAndOp - for && operation                                     */
7094 /*-----------------------------------------------------------------*/
7095 static void genAndOp (iCode *ic)
7096 {
7097   operand *left,*right, *result;
7098 /*     symbol *tlbl; */
7099
7100     FENTRY;
7101
7102     /* note here that && operations that are in an
7103     if statement are taken away by backPatchLabels
7104     only those used in arthmetic operations remain */
7105     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7106     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7107     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7108
7109     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7110
7111     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7112     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7113     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7114
7115     /* if both are bit variables */
7116 /*     if (AOP_TYPE(left) == AOP_CRY && */
7117 /*         AOP_TYPE(right) == AOP_CRY ) { */
7118 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7119 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7120 /*         pic16_outBitC(result); */
7121 /*     } else { */
7122 /*         tlbl = newiTempLabel(NULL); */
7123 /*         pic16_toBoolean(left);     */
7124 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7125 /*         pic16_toBoolean(right); */
7126 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7127 /*         pic16_outBitAcc(result); */
7128 /*     } */
7129
7130     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7131     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7132     pic16_freeAsmop(result,NULL,ic,TRUE);
7133 }
7134
7135
7136 /*-----------------------------------------------------------------*/
7137 /* genOrOp - for || operation                                      */
7138 /*-----------------------------------------------------------------*/
7139 /*
7140   tsd pic port -
7141   modified this code, but it doesn't appear to ever get called
7142 */
7143
7144 static void genOrOp (iCode *ic)
7145 {
7146   operand *left,*right, *result;
7147   symbol *tlbl;
7148
7149     FENTRY;  
7150
7151   /* note here that || operations that are in an
7152     if statement are taken away by backPatchLabels
7153     only those used in arthmetic operations remain */
7154     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7155     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7156     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7157
7158     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7159
7160     /* if both are bit variables */
7161     if (AOP_TYPE(left) == AOP_CRY &&
7162         AOP_TYPE(right) == AOP_CRY ) {
7163       pic16_emitcode("clrc","");
7164       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7165                AOP(left)->aopu.aop_dir,
7166                AOP(left)->aopu.aop_dir);
7167       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7168                AOP(right)->aopu.aop_dir,
7169                AOP(right)->aopu.aop_dir);
7170       pic16_emitcode("setc","");
7171
7172     } else {
7173         tlbl = newiTempLabel(NULL);
7174         pic16_toBoolean(left);
7175         emitSKPZ;
7176         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7177         pic16_toBoolean(right);
7178         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7179
7180         pic16_outBitAcc(result);
7181     }
7182
7183     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7184     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7185     pic16_freeAsmop(result,NULL,ic,TRUE);            
7186 }
7187
7188 /*-----------------------------------------------------------------*/
7189 /* isLiteralBit - test if lit == 2^n                               */
7190 /*-----------------------------------------------------------------*/
7191 static int isLiteralBit(unsigned long lit)
7192 {
7193     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7194     0x100L,0x200L,0x400L,0x800L,
7195     0x1000L,0x2000L,0x4000L,0x8000L,
7196     0x10000L,0x20000L,0x40000L,0x80000L,
7197     0x100000L,0x200000L,0x400000L,0x800000L,
7198     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7199     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7200     int idx;
7201     
7202     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7203     for(idx = 0; idx < 32; idx++)
7204         if(lit == pw[idx])
7205             return idx+1;
7206     return 0;
7207 }
7208
7209 /*-----------------------------------------------------------------*/
7210 /* continueIfTrue -                                                */
7211 /*-----------------------------------------------------------------*/
7212 static void continueIfTrue (iCode *ic)
7213 {
7214   FENTRY;
7215   if(IC_TRUE(ic))
7216     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7217   ic->generated = 1;
7218 }
7219
7220 /*-----------------------------------------------------------------*/
7221 /* jmpIfTrue -                                                     */
7222 /*-----------------------------------------------------------------*/
7223 static void jumpIfTrue (iCode *ic)
7224 {
7225   FENTRY;
7226   if(!IC_TRUE(ic))
7227     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7228   ic->generated = 1;
7229 }
7230
7231 /*-----------------------------------------------------------------*/
7232 /* jmpTrueOrFalse -                                                */
7233 /*-----------------------------------------------------------------*/
7234 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7235 {
7236   // ugly but optimized by peephole
7237   FENTRY;
7238   if(IC_TRUE(ic)){
7239     symbol *nlbl = newiTempLabel(NULL);
7240       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7241       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7242       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7243       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7244   } else {
7245     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7246     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7247   }
7248   ic->generated = 1;
7249 }
7250
7251 /*-----------------------------------------------------------------*/
7252 /* genAnd  - code for and                                          */
7253 /*-----------------------------------------------------------------*/
7254 static void genAnd (iCode *ic, iCode *ifx)
7255 {
7256   operand *left, *right, *result;
7257   int size, offset=0;  
7258   unsigned long lit = 0L;
7259   int bytelit = 0;
7260   resolvedIfx rIfx;
7261
7262     FENTRY;
7263     
7264   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7265   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7266   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7267
7268   resolveIfx(&rIfx,ifx);
7269
7270   /* if left is a literal & right is not then exchange them */
7271   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7272       AOP_NEEDSACC(left)) {
7273     operand *tmp = right ;
7274     right = left;
7275     left = tmp;
7276   }
7277
7278   /* if result = right then exchange them */
7279   if(pic16_sameRegs(AOP(result),AOP(right))){
7280     operand *tmp = right ;
7281     right = left;
7282     left = tmp;
7283   }
7284
7285   /* if right is bit then exchange them */
7286   if (AOP_TYPE(right) == AOP_CRY &&
7287       AOP_TYPE(left) != AOP_CRY){
7288     operand *tmp = right ;
7289     right = left;
7290     left = tmp;
7291   }
7292   if(AOP_TYPE(right) == AOP_LIT)
7293     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7294
7295   size = AOP_SIZE(result);
7296
7297   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7298
7299   // if(bit & yy)
7300   // result = bit & yy;
7301   if (AOP_TYPE(left) == AOP_CRY){
7302     // c = bit & literal;
7303     if(AOP_TYPE(right) == AOP_LIT){
7304       if(lit & 1) {
7305         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7306           // no change
7307           goto release;
7308         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7309       } else {
7310         // bit(result) = 0;
7311         if(size && (AOP_TYPE(result) == AOP_CRY)){
7312           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7313           goto release;
7314         }
7315         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7316           jumpIfTrue(ifx);
7317           goto release;
7318         }
7319         pic16_emitcode("clr","c");
7320       }
7321     } else {
7322       if (AOP_TYPE(right) == AOP_CRY){
7323         // c = bit & bit;
7324         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7325         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7326       } else {
7327         // c = bit & val;
7328         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7329         // c = lsb
7330         pic16_emitcode("rrc","a");
7331         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7332       }
7333     }
7334     // bit = c
7335     // val = c
7336     if(size)
7337       pic16_outBitC(result);
7338     // if(bit & ...)
7339     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7340       genIfxJump(ifx, "c");           
7341     goto release ;
7342   }
7343
7344   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7345   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7346   if((AOP_TYPE(right) == AOP_LIT) &&
7347      (AOP_TYPE(result) == AOP_CRY) &&
7348      (AOP_TYPE(left) != AOP_CRY)){
7349     int posbit = isLiteralBit(lit);
7350     /* left &  2^n */
7351     if(posbit){
7352       posbit--;
7353       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7354       // bit = left & 2^n
7355       if(size)
7356         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7357       // if(left &  2^n)
7358       else{
7359         if(ifx){
7360 /*
7361           if(IC_TRUE(ifx)) {
7362             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7363             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7364           } else {
7365             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7366             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7367           }
7368 */
7369         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7370         size = AOP_SIZE(left);
7371
7372         {
7373           int bp = posbit, ofs=0;
7374           
7375             while(bp > 7) {
7376               bp -= 8;
7377               ofs++;
7378             }
7379
7380           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7381                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7382
7383         }
7384 /*
7385           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7386                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7387 */
7388           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7389           
7390           ifx->generated = 1;
7391         }
7392         goto release;
7393       }
7394     } else {
7395       symbol *tlbl = newiTempLabel(NULL);
7396       int sizel = AOP_SIZE(left);
7397
7398       if(size)
7399         emitSETC;
7400
7401       while(sizel--) {
7402         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7403
7404           /* patch provided by Aaron Colwell */
7405           if((posbit = isLiteralBit(bytelit)) != 0) {
7406               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7407                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7408                                                 (posbit-1),0, PO_GPR_REGISTER));
7409
7410               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7411 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7412           } else {
7413               if (bytelit == 0xff) {
7414                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7415                    * a peephole could optimize it out -- VR */
7416                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7417               } else {
7418                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7419                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7420               }
7421
7422               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7423                             pic16_popGetLabel(tlbl->key));
7424           }
7425         
7426 #if 0
7427           /* old code, left here for reference -- VR 09/2004 */
7428           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7429           // byte ==  2^n ?
7430           if((posbit = isLiteralBit(bytelit)) != 0)
7431             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7432           else{
7433             if(bytelit != 0x0FFL)
7434               pic16_emitcode("anl","a,%s",
7435                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7436             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7437           }
7438 #endif
7439         }
7440         offset++;
7441       }
7442       // bit = left & literal
7443       if(size) {
7444         emitCLRC;
7445         pic16_emitpLabel(tlbl->key);
7446       }
7447       // if(left & literal)
7448       else {
7449         if(ifx) {
7450           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7451           ifx->generated = 1;
7452         }
7453         pic16_emitpLabel(tlbl->key);
7454         goto release;
7455       }
7456     }
7457
7458     pic16_outBitC(result);
7459     goto release ;
7460   }
7461
7462   /* if left is same as result */
7463   if(pic16_sameRegs(AOP(result),AOP(left))){
7464     int know_W = -1;
7465     for(;size--; offset++,lit>>=8) {
7466       if(AOP_TYPE(right) == AOP_LIT){
7467         switch(lit & 0xff) {
7468         case 0x00:
7469           /*  and'ing with 0 has clears the result */
7470 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7471           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7472           break;
7473         case 0xff:
7474           /* and'ing with 0xff is a nop when the result and left are the same */
7475           break;
7476
7477         default:
7478           {
7479             int p = pic16_my_powof2( (~lit) & 0xff );
7480             if(p>=0) {
7481               /* only one bit is set in the literal, so use a bcf instruction */
7482 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7483               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7484
7485             } else {
7486               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7487               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7488               if(know_W != (lit&0xff))
7489                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7490               know_W = lit &0xff;
7491               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7492             }
7493           }    
7494         }
7495       } else {
7496         if (AOP_TYPE(left) == AOP_ACC) {
7497           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7498         } else {                    
7499           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7500           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7501
7502         }
7503       }
7504     }
7505
7506   } else {
7507     // left & result in different registers
7508     if(AOP_TYPE(result) == AOP_CRY){
7509       // result = bit
7510       // if(size), result in bit
7511       // if(!size && ifx), conditional oper: if(left & right)
7512       symbol *tlbl = newiTempLabel(NULL);
7513       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7514       if(size)
7515         pic16_emitcode("setb","c");
7516       while(sizer--){
7517         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7518         pic16_emitcode("anl","a,%s",
7519                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7520         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7521         offset++;
7522       }
7523       if(size){
7524         CLRC;
7525         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7526         pic16_outBitC(result);
7527       } else if(ifx)
7528         jmpTrueOrFalse(ifx, tlbl);
7529     } else {
7530       for(;(size--);offset++) {
7531         // normal case
7532         // result = left & right
7533         if(AOP_TYPE(right) == AOP_LIT){
7534           int t = (lit >> (offset*8)) & 0x0FFL;
7535           switch(t) { 
7536           case 0x00:
7537             pic16_emitcode("clrf","%s",
7538                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7539             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7540             break;
7541           case 0xff:
7542             pic16_emitcode("movf","%s,w",
7543                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7544             pic16_emitcode("movwf","%s",
7545                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7546             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7547             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7548             break;
7549           default:
7550             pic16_emitcode("movlw","0x%x",t);
7551             pic16_emitcode("andwf","%s,w",
7552                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7553             pic16_emitcode("movwf","%s",
7554                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7555               
7556             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7557             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7558             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7559           }
7560           continue;
7561         }
7562
7563         if (AOP_TYPE(left) == AOP_ACC) {
7564           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7565           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7566         } else {
7567           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7568           pic16_emitcode("andwf","%s,w",
7569                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7570           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7571           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7572         }
7573         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7574         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7575       }
7576     }
7577   }
7578
7579   release :
7580     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7581   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7582   pic16_freeAsmop(result,NULL,ic,TRUE);     
7583 }
7584
7585 /*-----------------------------------------------------------------*/
7586 /* genOr  - code for or                                            */
7587 /*-----------------------------------------------------------------*/
7588 static void genOr (iCode *ic, iCode *ifx)
7589 {
7590     operand *left, *right, *result;
7591     int size, offset=0;
7592     unsigned long lit = 0L;
7593
7594     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7595
7596     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7597     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7598     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7599
7600     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7601
7602     /* if left is a literal & right is not then exchange them */
7603     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7604         AOP_NEEDSACC(left)) {
7605         operand *tmp = right ;
7606         right = left;
7607         left = tmp;
7608     }
7609
7610     /* if result = right then exchange them */
7611     if(pic16_sameRegs(AOP(result),AOP(right))){
7612         operand *tmp = right ;
7613         right = left;
7614         left = tmp;
7615     }
7616
7617     /* if right is bit then exchange them */
7618     if (AOP_TYPE(right) == AOP_CRY &&
7619         AOP_TYPE(left) != AOP_CRY){
7620         operand *tmp = right ;
7621         right = left;
7622         left = tmp;
7623     }
7624
7625     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7626
7627     if(AOP_TYPE(right) == AOP_LIT)
7628         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7629
7630     size = AOP_SIZE(result);
7631
7632     // if(bit | yy)
7633     // xx = bit | yy;
7634     if (AOP_TYPE(left) == AOP_CRY){
7635         if(AOP_TYPE(right) == AOP_LIT){
7636             // c = bit & literal;
7637             if(lit){
7638                 // lit != 0 => result = 1
7639                 if(AOP_TYPE(result) == AOP_CRY){
7640                   if(size)
7641                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7642                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7643                   //     AOP(result)->aopu.aop_dir,
7644                   //     AOP(result)->aopu.aop_dir);
7645                     else if(ifx)
7646                         continueIfTrue(ifx);
7647                     goto release;
7648                 }
7649             } else {
7650                 // lit == 0 => result = left
7651                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7652                     goto release;
7653                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7654             }
7655         } else {
7656             if (AOP_TYPE(right) == AOP_CRY){
7657               if(pic16_sameRegs(AOP(result),AOP(left))){
7658                 // c = bit | bit;
7659                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7660                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7661                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7662
7663                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7664                          AOP(result)->aopu.aop_dir,
7665                          AOP(result)->aopu.aop_dir);
7666                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7667                          AOP(right)->aopu.aop_dir,
7668                          AOP(right)->aopu.aop_dir);
7669                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7670                          AOP(result)->aopu.aop_dir,
7671                          AOP(result)->aopu.aop_dir);
7672               } else {
7673                 if( AOP_TYPE(result) == AOP_ACC) {
7674                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7675                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7676                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7677                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7678
7679                 } else {
7680
7681                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7682                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7683                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7684                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7685
7686                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7687                                  AOP(result)->aopu.aop_dir,
7688                                  AOP(result)->aopu.aop_dir);
7689                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7690                                  AOP(right)->aopu.aop_dir,
7691                                  AOP(right)->aopu.aop_dir);
7692                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7693                                  AOP(left)->aopu.aop_dir,
7694                                  AOP(left)->aopu.aop_dir);
7695                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7696                                  AOP(result)->aopu.aop_dir,
7697                                  AOP(result)->aopu.aop_dir);
7698                 }
7699               }
7700             } else {
7701                 // c = bit | val;
7702                 symbol *tlbl = newiTempLabel(NULL);
7703                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7704
7705
7706                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7707                 if( AOP_TYPE(right) == AOP_ACC) {
7708                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7709                   emitSKPNZ;
7710                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7711                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7712                 }
7713
7714
7715
7716                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7717                     pic16_emitcode(";XXX setb","c");
7718                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7719                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7720                 pic16_toBoolean(right);
7721                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7722                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7723                     jmpTrueOrFalse(ifx, tlbl);
7724                     goto release;
7725                 } else {
7726                     CLRC;
7727                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7728                 }
7729             }
7730         }
7731         // bit = c
7732         // val = c
7733         if(size)
7734             pic16_outBitC(result);
7735         // if(bit | ...)
7736         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7737             genIfxJump(ifx, "c");           
7738         goto release ;
7739     }
7740
7741     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7742     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7743     if((AOP_TYPE(right) == AOP_LIT) &&
7744        (AOP_TYPE(result) == AOP_CRY) &&
7745        (AOP_TYPE(left) != AOP_CRY)){
7746         if(lit){
7747           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7748             // result = 1
7749             if(size)
7750                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7751             else 
7752                 continueIfTrue(ifx);
7753             goto release;
7754         } else {
7755           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7756             // lit = 0, result = boolean(left)
7757             if(size)
7758                 pic16_emitcode(";XXX setb","c");
7759             pic16_toBoolean(right);
7760             if(size){
7761                 symbol *tlbl = newiTempLabel(NULL);
7762                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7763                 CLRC;
7764                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7765             } else {
7766                 genIfxJump (ifx,"a");
7767                 goto release;
7768             }
7769         }
7770         pic16_outBitC(result);
7771         goto release ;
7772     }
7773
7774     /* if left is same as result */
7775     if(pic16_sameRegs(AOP(result),AOP(left))){
7776       int know_W = -1;
7777       for(;size--; offset++,lit>>=8) {
7778         if(AOP_TYPE(right) == AOP_LIT){
7779           if((lit & 0xff) == 0)
7780             /*  or'ing with 0 has no effect */
7781             continue;
7782           else {
7783             int p = pic16_my_powof2(lit & 0xff);
7784             if(p>=0) {
7785               /* only one bit is set in the literal, so use a bsf instruction */
7786               pic16_emitpcode(POC_BSF,
7787                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7788             } else {
7789               if(know_W != (lit & 0xff))
7790                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7791               know_W = lit & 0xff;
7792               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7793             }
7794                     
7795           }
7796         } else {
7797           if (AOP_TYPE(left) == AOP_ACC) {
7798             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7799             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7800           } else {                  
7801             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7802             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7803
7804             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7805             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7806
7807           }
7808         }
7809       }
7810     } else {
7811         // left & result in different registers
7812         if(AOP_TYPE(result) == AOP_CRY){
7813             // result = bit
7814             // if(size), result in bit
7815             // if(!size && ifx), conditional oper: if(left | right)
7816             symbol *tlbl = newiTempLabel(NULL);
7817             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7818             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7819
7820
7821             if(size)
7822                 pic16_emitcode(";XXX setb","c");
7823             while(sizer--){
7824                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7825                 pic16_emitcode(";XXX orl","a,%s",
7826                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7827                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7828                 offset++;
7829             }
7830             if(size){
7831                 CLRC;
7832                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7833                 pic16_outBitC(result);
7834             } else if(ifx)
7835                 jmpTrueOrFalse(ifx, tlbl);
7836         } else for(;(size--);offset++){
7837           // normal case
7838           // result = left & right
7839           if(AOP_TYPE(right) == AOP_LIT){
7840             int t = (lit >> (offset*8)) & 0x0FFL;
7841             switch(t) { 
7842             case 0x00:
7843               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7844               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7845
7846               pic16_emitcode("movf","%s,w",
7847                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7848               pic16_emitcode("movwf","%s",
7849                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7850               break;
7851             default:
7852               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7853               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7854               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7855
7856               pic16_emitcode("movlw","0x%x",t);
7857               pic16_emitcode("iorwf","%s,w",
7858                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7859               pic16_emitcode("movwf","%s",
7860                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7861               
7862             }
7863             continue;
7864           }
7865
7866           // faster than result <- left, anl result,right
7867           // and better if result is SFR
7868           if (AOP_TYPE(left) == AOP_ACC) {
7869             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7870             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7871           } else {
7872             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7873             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7874
7875             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7876             pic16_emitcode("iorwf","%s,w",
7877                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7878           }
7879           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7880           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7881         }
7882     }
7883
7884 release :
7885     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7886     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7887     pic16_freeAsmop(result,NULL,ic,TRUE);     
7888 }
7889
7890 /*-----------------------------------------------------------------*/
7891 /* genXor - code for xclusive or                                   */
7892 /*-----------------------------------------------------------------*/
7893 static void genXor (iCode *ic, iCode *ifx)
7894 {
7895   operand *left, *right, *result;
7896   int size, offset=0;
7897   unsigned long lit = 0L;
7898
7899   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7900
7901   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7902   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7903   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7904
7905   /* if left is a literal & right is not ||
7906      if left needs acc & right does not */
7907   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7908       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7909     operand *tmp = right ;
7910     right = left;
7911     left = tmp;
7912   }
7913
7914   /* if result = right then exchange them */
7915   if(pic16_sameRegs(AOP(result),AOP(right))){
7916     operand *tmp = right ;
7917     right = left;
7918     left = tmp;
7919   }
7920
7921   /* if right is bit then exchange them */
7922   if (AOP_TYPE(right) == AOP_CRY &&
7923       AOP_TYPE(left) != AOP_CRY){
7924     operand *tmp = right ;
7925     right = left;
7926     left = tmp;
7927   }
7928   if(AOP_TYPE(right) == AOP_LIT)
7929     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7930
7931   size = AOP_SIZE(result);
7932
7933   // if(bit ^ yy)
7934   // xx = bit ^ yy;
7935   if (AOP_TYPE(left) == AOP_CRY){
7936     if(AOP_TYPE(right) == AOP_LIT){
7937       // c = bit & literal;
7938       if(lit>>1){
7939         // lit>>1  != 0 => result = 1
7940         if(AOP_TYPE(result) == AOP_CRY){
7941           if(size)
7942             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7943             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7944           else if(ifx)
7945             continueIfTrue(ifx);
7946           goto release;
7947         }
7948         pic16_emitcode("setb","c");
7949       } else{
7950         // lit == (0 or 1)
7951         if(lit == 0){
7952           // lit == 0, result = left
7953           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7954             goto release;
7955           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7956         } else{
7957           // lit == 1, result = not(left)
7958           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7959             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7960             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7961             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7962             goto release;
7963           } else {
7964             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7965             pic16_emitcode("cpl","c");
7966           }
7967         }
7968       }
7969
7970     } else {
7971       // right != literal
7972       symbol *tlbl = newiTempLabel(NULL);
7973       if (AOP_TYPE(right) == AOP_CRY){
7974         // c = bit ^ bit;
7975         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7976       }
7977       else{
7978         int sizer = AOP_SIZE(right);
7979         // c = bit ^ val
7980         // if val>>1 != 0, result = 1
7981         pic16_emitcode("setb","c");
7982         while(sizer){
7983           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7984           if(sizer == 1)
7985             // test the msb of the lsb
7986             pic16_emitcode("anl","a,#0xfe");
7987           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7988           sizer--;
7989         }
7990         // val = (0,1)
7991         pic16_emitcode("rrc","a");
7992       }
7993       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7994       pic16_emitcode("cpl","c");
7995       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7996     }
7997     // bit = c
7998     // val = c
7999     if(size)
8000       pic16_outBitC(result);
8001     // if(bit | ...)
8002     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8003       genIfxJump(ifx, "c");           
8004     goto release ;
8005   }
8006
8007   if(pic16_sameRegs(AOP(result),AOP(left))){
8008     /* if left is same as result */
8009     for(;size--; offset++) {
8010       if(AOP_TYPE(right) == AOP_LIT){
8011         int t  = (lit >> (offset*8)) & 0x0FFL;
8012         if(t == 0x00L)
8013           continue;
8014         else
8015           if (IS_AOP_PREG(left)) {
8016             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8017             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8018             pic16_aopPut(AOP(result),"a",offset);
8019           } else {
8020             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8021             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8022             pic16_emitcode("xrl","%s,%s",
8023                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8024                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8025           }
8026       } else {
8027         if (AOP_TYPE(left) == AOP_ACC)
8028           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8029         else {
8030           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8031           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8032 /*
8033           if (IS_AOP_PREG(left)) {
8034             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8035             pic16_aopPut(AOP(result),"a",offset);
8036           } else
8037             pic16_emitcode("xrl","%s,a",
8038                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8039 */
8040         }
8041       }
8042     }
8043   } else {
8044     // left & result in different registers
8045     if(AOP_TYPE(result) == AOP_CRY){
8046       // result = bit
8047       // if(size), result in bit
8048       // if(!size && ifx), conditional oper: if(left ^ right)
8049       symbol *tlbl = newiTempLabel(NULL);
8050       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8051       if(size)
8052         pic16_emitcode("setb","c");
8053       while(sizer--){
8054         if((AOP_TYPE(right) == AOP_LIT) &&
8055            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8056           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8057         } else {
8058           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8059           pic16_emitcode("xrl","a,%s",
8060                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8061         }
8062         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8063         offset++;
8064       }
8065       if(size){
8066         CLRC;
8067         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8068         pic16_outBitC(result);
8069       } else if(ifx)
8070         jmpTrueOrFalse(ifx, tlbl);
8071     } else for(;(size--);offset++){
8072       // normal case
8073       // result = left & right
8074       if(AOP_TYPE(right) == AOP_LIT){
8075         int t = (lit >> (offset*8)) & 0x0FFL;
8076         switch(t) { 
8077         case 0x00:
8078           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8079           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8080           pic16_emitcode("movf","%s,w",
8081                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8082           pic16_emitcode("movwf","%s",
8083                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8084           break;
8085         case 0xff:
8086           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8087           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8088           pic16_emitcode("comf","%s,w",
8089                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8090           pic16_emitcode("movwf","%s",
8091                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8092           break;
8093         default:
8094           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8095           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8096           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8097           pic16_emitcode("movlw","0x%x",t);
8098           pic16_emitcode("xorwf","%s,w",
8099                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8100           pic16_emitcode("movwf","%s",
8101                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8102
8103         }
8104         continue;
8105       }
8106
8107       // faster than result <- left, anl result,right
8108       // and better if result is SFR
8109       if (AOP_TYPE(left) == AOP_ACC) {
8110         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8111         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8112       } else {
8113         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8114         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8115         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8116         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8117       }
8118       if ( AOP_TYPE(result) != AOP_ACC){
8119         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8120         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8121       }
8122     }
8123   }
8124
8125   release :
8126     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8127   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8128   pic16_freeAsmop(result,NULL,ic,TRUE);     
8129 }
8130
8131 /*-----------------------------------------------------------------*/
8132 /* genInline - write the inline code out                           */
8133 /*-----------------------------------------------------------------*/
8134 static void genInline (iCode *ic)
8135 {
8136   char *buffer, *bp, *bp1;
8137     
8138         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8139
8140         _G.inLine += (!options.asmpeep);
8141
8142         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8143         strcpy(buffer,IC_INLINE(ic));
8144         
8145         while((bp1=strstr(bp, "\\n"))) {
8146           *bp1++ = '\n';
8147           *bp1++ = ' ';
8148           bp = bp1;
8149         }
8150         bp = bp1 = buffer;
8151
8152 #if 0
8153   /* This is an experimental code for #pragma inline
8154      and is temporarily disabled for 2.5.0 release */
8155         if(asmInlineMap)
8156         {
8157           symbol *sym;
8158           char *s;
8159           char *cbuf;
8160           int cblen;
8161
8162             cbuf = Safe_strdup(buffer);
8163             cblen = strlen(buffer)+1;
8164             memset(cbuf, 0, cblen);
8165
8166             bp = buffer;
8167             bp1 = cbuf;
8168             while(*bp) {
8169               if(*bp != '%')*bp1++ = *bp++;
8170               else {
8171                 int i;
8172
8173                   bp++;
8174                   i = *bp - '0';
8175                   if(i>elementsInSet(asmInlineMap))break;
8176                   
8177                   bp++;
8178                   s = indexSet(asmInlineMap, i);
8179                   DEBUGpc("searching symbol s = `%s'", s);
8180                   sym = findSym(SymbolTab, NULL, s);
8181
8182                   if(sym->reqv) {
8183                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8184                   } else {
8185                     strcat(bp1, sym->rname);
8186                   }
8187                   
8188                   while(*bp1)bp1++;
8189               }
8190               
8191               if(strlen(bp1) > cblen - 16) {
8192                 int i = strlen(cbuf);
8193                 cblen += 50;
8194                 cbuf = realloc(cbuf, cblen);
8195                 memset(cbuf+i, 0, 50);
8196                 bp1 = cbuf + i;
8197               }
8198             }
8199             
8200             free(buffer);
8201             buffer = Safe_strdup( cbuf );
8202             free(cbuf);
8203             
8204             bp = bp1 = buffer;
8205         }
8206 #endif  /* 0 */
8207
8208         /* emit each line as a code */
8209         while (*bp) {
8210                 if (*bp == '\n') {
8211                         *bp++ = '\0';
8212
8213                         if(*bp1)
8214                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8215                         bp1 = bp;
8216                 } else {
8217                         if (*bp == ':') {
8218                                 bp++;
8219                                 *bp = '\0';
8220                                 bp++;
8221
8222                                 /* print label, use this special format with NULL directive
8223                                  * to denote that the argument should not be indented with tab */
8224                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8225                                 bp1 = bp;
8226                         } if (*bp == ';') {
8227                                 /* advance to end of line (prevent splitting of comments at ':' */
8228                                 while (*bp && *bp != '\n') {
8229                                         bp++;
8230                                 } // while
8231                         } else
8232                                 bp++;
8233                 }
8234         }
8235
8236         if ((bp1 != bp) && *bp1)
8237                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8238
8239
8240     Safe_free(buffer);
8241
8242     _G.inLine -= (!options.asmpeep);
8243 }
8244
8245 /*-----------------------------------------------------------------*/
8246 /* genRRC - rotate right with carry                                */
8247 /*-----------------------------------------------------------------*/
8248 static void genRRC (iCode *ic)
8249 {
8250   operand *left , *result ;
8251   int size, offset = 0, same;
8252
8253   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8254
8255   /* rotate right with carry */
8256   left = IC_LEFT(ic);
8257   result=IC_RESULT(ic);
8258   pic16_aopOp (left,ic,FALSE);
8259   pic16_aopOp (result,ic,TRUE);
8260
8261   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8262
8263   same = pic16_sameRegs(AOP(result),AOP(left));
8264
8265   size = AOP_SIZE(result);    
8266
8267   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8268
8269   /* get the lsb and put it into the carry */
8270   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8271
8272   offset = 0 ;
8273
8274   while(size--) {
8275
8276     if(same) {
8277       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8278     } else {
8279       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8280       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8281     }
8282
8283     offset++;
8284   }
8285
8286   pic16_freeAsmop(left,NULL,ic,TRUE);
8287   pic16_freeAsmop(result,NULL,ic,TRUE);
8288 }
8289
8290 /*-----------------------------------------------------------------*/
8291 /* genRLC - generate code for rotate left with carry               */
8292 /*-----------------------------------------------------------------*/
8293 static void genRLC (iCode *ic)
8294 {    
8295   operand *left , *result ;
8296   int size, offset = 0;
8297   int same;
8298
8299   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8300   /* rotate right with carry */
8301   left = IC_LEFT(ic);
8302   result=IC_RESULT(ic);
8303   pic16_aopOp (left,ic,FALSE);
8304   pic16_aopOp (result,ic,TRUE);
8305
8306   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8307
8308   same = pic16_sameRegs(AOP(result),AOP(left));
8309
8310   /* move it to the result */
8311   size = AOP_SIZE(result);    
8312
8313   /* get the msb and put it into the carry */
8314   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8315
8316   offset = 0 ;
8317
8318   while(size--) {
8319
8320     if(same) {
8321       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8322     } else {
8323       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8324       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8325     }
8326
8327     offset++;
8328   }
8329
8330
8331   pic16_freeAsmop(left,NULL,ic,TRUE);
8332   pic16_freeAsmop(result,NULL,ic,TRUE);
8333 }
8334
8335
8336 /* gpasm can get the highest order bit with HIGH/UPPER
8337  * so the following probably is not needed -- VR */
8338  
8339 /*-----------------------------------------------------------------*/
8340 /* genGetHbit - generates code get highest order bit               */
8341 /*-----------------------------------------------------------------*/
8342 static void genGetHbit (iCode *ic)
8343 {
8344     operand *left, *result;
8345     left = IC_LEFT(ic);
8346     result=IC_RESULT(ic);
8347     pic16_aopOp (left,ic,FALSE);
8348     pic16_aopOp (result,ic,FALSE);
8349
8350     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8351     /* get the highest order byte into a */
8352     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8353     if(AOP_TYPE(result) == AOP_CRY){
8354         pic16_emitcode("rlc","a");
8355         pic16_outBitC(result);
8356     }
8357     else{
8358         pic16_emitcode("rl","a");
8359         pic16_emitcode("anl","a,#0x01");
8360         pic16_outAcc(result);
8361     }
8362
8363
8364     pic16_freeAsmop(left,NULL,ic,TRUE);
8365     pic16_freeAsmop(result,NULL,ic,TRUE);
8366 }
8367
8368 #if 0
8369 /*-----------------------------------------------------------------*/
8370 /* AccRol - rotate left accumulator by known count                 */
8371 /*-----------------------------------------------------------------*/
8372 static void AccRol (int shCount)
8373 {
8374     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8375     shCount &= 0x0007;              // shCount : 0..7
8376     switch(shCount){
8377         case 0 :
8378             break;
8379         case 1 :
8380             pic16_emitcode("rl","a");
8381             break;
8382         case 2 :
8383             pic16_emitcode("rl","a");
8384             pic16_emitcode("rl","a");
8385             break;
8386         case 3 :
8387             pic16_emitcode("swap","a");
8388             pic16_emitcode("rr","a");
8389             break;
8390         case 4 :
8391             pic16_emitcode("swap","a");
8392             break;
8393         case 5 :
8394             pic16_emitcode("swap","a");
8395             pic16_emitcode("rl","a");
8396             break;
8397         case 6 :
8398             pic16_emitcode("rr","a");
8399             pic16_emitcode("rr","a");
8400             break;
8401         case 7 :
8402             pic16_emitcode("rr","a");
8403             break;
8404     }
8405 }
8406 #endif
8407
8408 /*-----------------------------------------------------------------*/
8409 /* AccLsh - left shift accumulator by known count                  */
8410 /*-----------------------------------------------------------------*/
8411 static void AccLsh (int shCount)
8412 {
8413         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8414         switch(shCount){
8415                 case 0 :
8416                         return;
8417                         break;
8418                 case 1 :
8419                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8420                         break;
8421                 case 2 :
8422                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8423                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8424                         break;
8425                 case 3 :
8426                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8427                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8428                         break;
8429                 case 4 :
8430                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8431                         break;
8432                 case 5 :
8433                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8434                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8435                         break;
8436                 case 6 :
8437                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8438                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8439                         break;
8440                 case 7 :
8441                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8442                         break;
8443         }
8444
8445         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8446 }
8447
8448 /*-----------------------------------------------------------------*/
8449 /* AccRsh - right shift accumulator by known count                 */
8450 /*-----------------------------------------------------------------*/
8451 static void AccRsh (int shCount, int andmask)
8452 {
8453         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8454         switch(shCount){
8455                 case 0 :
8456                         return; break;
8457                 case 1 :
8458                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8459                         break;
8460                 case 2 :
8461                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8462                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8463                         break;
8464                 case 3 :
8465                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8466                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8467                         break;
8468                 case 4 :
8469                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8470                         break;
8471                 case 5 :
8472                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8473                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8474                         break;
8475                 case 6 :
8476                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8477                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8478                         break;
8479                 case 7 :
8480                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8481                         break;
8482         }
8483         
8484         if(andmask)
8485                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8486         else
8487                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8488 }
8489
8490 #if 0
8491 /*-----------------------------------------------------------------*/
8492 /* AccSRsh - signed right shift accumulator by known count                 */
8493 /*-----------------------------------------------------------------*/
8494 static void AccSRsh (int shCount)
8495 {
8496     symbol *tlbl ;
8497     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8498     if(shCount != 0){
8499         if(shCount == 1){
8500             pic16_emitcode("mov","c,acc.7");
8501             pic16_emitcode("rrc","a");
8502         } else if(shCount == 2){
8503             pic16_emitcode("mov","c,acc.7");
8504             pic16_emitcode("rrc","a");
8505             pic16_emitcode("mov","c,acc.7");
8506             pic16_emitcode("rrc","a");
8507         } else {
8508             tlbl = newiTempLabel(NULL);
8509             /* rotate right accumulator */
8510             AccRol(8 - shCount);
8511             /* and kill the higher order bits */
8512             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8513             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8514             pic16_emitcode("orl","a,#0x%02x",
8515                      (unsigned char)~SRMask[shCount]);
8516             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8517         }
8518     }
8519 }
8520 #endif
8521
8522 /*-----------------------------------------------------------------*/
8523 /* shiftR1Left2Result - shift right one byte from left to result   */
8524 /*-----------------------------------------------------------------*/
8525 static void shiftR1Left2ResultSigned (operand *left, int offl,
8526                                 operand *result, int offr,
8527                                 int shCount)
8528 {
8529   int same;
8530
8531   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8532
8533   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8534
8535   switch(shCount) {
8536   case 1:
8537     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8538     if(same) 
8539       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8540     else {
8541       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8542       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8543     }
8544
8545     break;
8546   case 2:
8547
8548     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8549     if(same) 
8550       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8551     else {
8552       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8553       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8554     }
8555     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8556     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8557
8558     break;
8559
8560   case 3:
8561     if(same)
8562       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8563     else {
8564       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8565       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8566     }
8567
8568     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8569     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8570     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8571
8572     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8573     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8574
8575     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8576     break;
8577
8578   case 4:
8579     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8580     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8581     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8582     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8583     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8584     break;
8585   case 5:
8586     if(same) {
8587       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8588     } else {
8589       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8590       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8591     }
8592     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8593     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8594     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8595     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8596     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8597     break;
8598
8599   case 6:
8600     if(same) {
8601       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8602       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8603       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8604       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8605       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8606       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8607     } else {
8608       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8609       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8610       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8611       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8612       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8613     }
8614     break;
8615
8616   case 7:
8617     if(same) {
8618       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8619       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8620       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8621       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8622     } else {
8623       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8624       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8625       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8626     }
8627
8628   default:
8629     break;
8630   }
8631 }
8632
8633 /*-----------------------------------------------------------------*/
8634 /* shiftR1Left2Result - shift right one byte from left to result   */
8635 /*-----------------------------------------------------------------*/
8636 static void shiftR1Left2Result (operand *left, int offl,
8637                                 operand *result, int offr,
8638                                 int shCount, int sign)
8639 {
8640   int same;
8641
8642   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8643
8644   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8645
8646   /* Copy the msb into the carry if signed. */
8647   if(sign) {
8648     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8649     return;
8650   }
8651
8652
8653
8654   switch(shCount) {
8655   case 1:
8656     emitCLRC;
8657     if(same) 
8658       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8659     else {
8660       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8661       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8662     }
8663     break;
8664   case 2:
8665     emitCLRC;
8666     if(same) {
8667       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8668     } else {
8669       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8670       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8671     }
8672     emitCLRC;
8673     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8674
8675     break;
8676   case 3:
8677     if(same)
8678       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8679     else {
8680       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8681       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8682     }
8683
8684     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8685     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8686     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8687     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8688     break;
8689       
8690   case 4:
8691     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8692     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8693     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8694     break;
8695
8696   case 5:
8697     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8698     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8699     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8700     //emitCLRC;
8701     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8702
8703     break;
8704   case 6:
8705
8706     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8707     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8708     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8709     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8710     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8711     break;
8712
8713   case 7:
8714
8715     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8716     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8717     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8718
8719     break;
8720
8721   default:
8722     break;
8723   }
8724 }
8725
8726 /*-----------------------------------------------------------------*/
8727 /* shiftL1Left2Result - shift left one byte from left to result    */
8728 /*-----------------------------------------------------------------*/
8729 static void shiftL1Left2Result (operand *left, int offl,
8730                                 operand *result, int offr, int shCount)
8731 {
8732   int same;
8733
8734   //    char *l;
8735   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8736
8737   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8738   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8739     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8740     //    MOVA(l);
8741     /* shift left accumulator */
8742     //AccLsh(shCount); // don't comment out just yet...
8743   //    pic16_aopPut(AOP(result),"a",offr);
8744
8745   switch(shCount) {
8746   case 1:
8747     /* Shift left 1 bit position */
8748     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8749     if(same) {
8750       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8751     } else {
8752       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8753       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8754     }
8755     break;
8756   case 2:
8757     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8758     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8759     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8760     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8761     break;
8762   case 3:
8763     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8764     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8765     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8766     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8767     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8768     break;
8769   case 4:
8770     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8771     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8772     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8773     break;
8774   case 5:
8775     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8776     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8777     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8778     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8779     break;
8780   case 6:
8781     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8782     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8783     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8784     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8785     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8786     break;
8787   case 7:
8788     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8789     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8790     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8791     break;
8792
8793   default:
8794     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8795   }
8796
8797 }
8798
8799 /*-----------------------------------------------------------------*/
8800 /* movLeft2Result - move byte from left to result                  */
8801 /*-----------------------------------------------------------------*/
8802 static void movLeft2Result (operand *left, int offl,
8803                             operand *result, int offr)
8804 {
8805   char *l;
8806   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8807   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8808     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8809
8810     if (*l == '@' && (IS_AOP_PREG(result))) {
8811       pic16_emitcode("mov","a,%s",l);
8812       pic16_aopPut(AOP(result),"a",offr);
8813     } else {
8814       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8815       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8816     }
8817   }
8818 }
8819
8820 /*-----------------------------------------------------------------*/
8821 /* shiftL2Left2Result - shift left two bytes from left to result   */
8822 /*-----------------------------------------------------------------*/
8823 static void shiftL2Left2Result (operand *left, int offl,
8824                                 operand *result, int offr, int shCount)
8825 {
8826   int same = pic16_sameRegs(AOP(result), AOP(left));
8827   int i;
8828
8829   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8830
8831   if (same && (offl != offr)) { // shift bytes
8832     if (offr > offl) {
8833        for(i=1;i>-1;i--) {
8834          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8835          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8836        }
8837     } else { // just treat as different later on
8838                 same = 0;
8839     }
8840   }
8841
8842   if(same) {
8843     switch(shCount) {
8844     case 0:
8845       break;
8846     case 1:
8847     case 2:
8848     case 3:
8849
8850       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8851       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8852       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8853
8854       while(--shCount) {
8855                 emitCLRC;
8856                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8857                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8858       }
8859
8860       break;
8861     case 4:
8862     case 5:
8863       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8864       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8865       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8866       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8867       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8868       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8869       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8870       if(shCount >=5) {
8871                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8872                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8873       }
8874       break;
8875     case 6:
8876       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8877       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8878       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8879       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8880       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8881       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8882       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8883       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8884       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8885       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8886       break;
8887     case 7:
8888       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8889       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8890       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8891       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8892       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8893     }
8894
8895   } else {
8896     switch(shCount) {
8897     case 0:
8898       break;
8899     case 1:
8900     case 2:
8901     case 3:
8902       /* note, use a mov/add for the shift since the mov has a
8903          chance of getting optimized out */
8904       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8905       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8906       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8907       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8908       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8909
8910       while(--shCount) {
8911                 emitCLRC;
8912                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8913                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8914       }
8915       break;
8916
8917     case 4:
8918     case 5:
8919       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8920       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8921       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8922       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8923       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8924       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8925       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8926       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8927
8928
8929       if(shCount == 5) {
8930                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8931                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8932       }
8933       break;
8934     case 6:
8935       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8936       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8937       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8938       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8939
8940       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8941       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8942       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8943       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8944       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8945       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8946       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8947       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8948       break;
8949     case 7:
8950       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8951       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8952       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8953       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8954       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8955     }
8956   }
8957
8958 }
8959 /*-----------------------------------------------------------------*/
8960 /* shiftR2Left2Result - shift right two bytes from left to result  */
8961 /*-----------------------------------------------------------------*/
8962 static void shiftR2Left2Result (operand *left, int offl,
8963                                 operand *result, int offr,
8964                                 int shCount, int sign)
8965 {
8966   int same = pic16_sameRegs(AOP(result), AOP(left));
8967   int i;
8968   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8969
8970   if (same && (offl != offr)) { // shift right bytes
8971     if (offr < offl) {
8972        for(i=0;i<2;i++) {
8973          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8974          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8975        }
8976     } else { // just treat as different later on
8977                 same = 0;
8978     }
8979   }
8980
8981   switch(shCount) {
8982   case 0:
8983     break;
8984   case 1:
8985   case 2:
8986   case 3:
8987     if(sign)
8988       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8989     else
8990       emitCLRC;
8991
8992     if(same) {
8993       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8994       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8995     } else {
8996       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8997       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8998       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8999       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9000     }
9001
9002     while(--shCount) {
9003       if(sign)
9004                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9005       else
9006                 emitCLRC;
9007       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9008       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9009     }
9010     break;
9011   case 4:
9012   case 5:
9013     if(same) {
9014
9015       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9016       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9017       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9018
9019       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9020       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9021       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9022       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9023     } else {
9024       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9025       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9026       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027
9028       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9029       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9030       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9031       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9032       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9033     }
9034
9035     if(shCount >=5) {
9036       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9037       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9038     }
9039
9040     if(sign) {
9041       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9042       pic16_emitpcode(POC_BTFSC, 
9043                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9044       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9045     }
9046
9047     break;
9048
9049   case 6:
9050     if(same) {
9051
9052       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9053       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9054
9055       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9056       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9057       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9058       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9059       if(sign) {
9060         pic16_emitpcode(POC_BTFSC, 
9061                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9062         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9063       }
9064       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9065       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9066       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9067       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9068     } else {
9069       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9070       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9071       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9072       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9073       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9074       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9075       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9076       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9077       if(sign) {
9078         pic16_emitpcode(POC_BTFSC, 
9079                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9080         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9081       }
9082       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9083       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9084
9085         
9086     }
9087
9088     break;
9089   case 7:
9090     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9091     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9092     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9093     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9094     if(sign) {
9095       emitSKPNC;
9096       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9097     } else 
9098       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9099   }
9100 }
9101
9102
9103 /*-----------------------------------------------------------------*/
9104 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9105 /*-----------------------------------------------------------------*/
9106 static void shiftLLeftOrResult (operand *left, int offl,
9107                                 operand *result, int offr, int shCount)
9108 {
9109     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9110
9111     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9112     /* shift left accumulator */
9113     AccLsh(shCount);
9114     /* or with result */
9115     /* back to result */
9116     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9117 }
9118
9119 /*-----------------------------------------------------------------*/
9120 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9121 /*-----------------------------------------------------------------*/
9122 static void shiftRLeftOrResult (operand *left, int offl,
9123                                 operand *result, int offr, int shCount)
9124 {
9125     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9126     
9127     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9128     /* shift right accumulator */
9129     AccRsh(shCount, 1);
9130     /* or with result */
9131     /* back to result */
9132     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9133 }
9134
9135 /*-----------------------------------------------------------------*/
9136 /* genlshOne - left shift a one byte quantity by known count       */
9137 /*-----------------------------------------------------------------*/
9138 static void genlshOne (operand *result, operand *left, int shCount)
9139 {       
9140     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9141     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9142 }
9143
9144 /*-----------------------------------------------------------------*/
9145 /* genlshTwo - left shift two bytes by known amount != 0           */
9146 /*-----------------------------------------------------------------*/
9147 static void genlshTwo (operand *result,operand *left, int shCount)
9148 {
9149     int size;
9150     
9151     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9152     size = pic16_getDataSize(result);
9153
9154     /* if shCount >= 8 */
9155     if (shCount >= 8) {
9156         shCount -= 8 ;
9157
9158         if (size > 1){
9159             if (shCount)
9160                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9161             else 
9162                 movLeft2Result(left, LSB, result, MSB16);
9163         }
9164         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9165     }
9166
9167     /*  1 <= shCount <= 7 */
9168     else {  
9169         if(size == 1)
9170             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9171         else 
9172             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9173     }
9174 }
9175
9176 /*-----------------------------------------------------------------*/
9177 /* shiftLLong - shift left one long from left to result            */
9178 /* offr = LSB or MSB16                                             */
9179 /*-----------------------------------------------------------------*/
9180 static void shiftLLong (operand *left, operand *result, int offr )
9181 {
9182     int size = AOP_SIZE(result);
9183     int same = pic16_sameRegs(AOP(left),AOP(result));
9184         int i;
9185
9186     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9187
9188         if (same && (offr == MSB16)) { //shift one byte
9189                 for(i=size-1;i>=MSB16;i--) {
9190                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9191                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9192                 }
9193         } else {
9194                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9195         }
9196         
9197     if (size > LSB+offr ){
9198                 if (same) {
9199                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9200                 } else {
9201                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9202                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9203                 }
9204          }
9205
9206     if(size > MSB16+offr){
9207                 if (same) {
9208                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9209                 } else {
9210                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9211                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9212                 }
9213     }
9214
9215     if(size > MSB24+offr){
9216                 if (same) {
9217                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9218                 } else {
9219                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9220                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9221                 }
9222     }
9223
9224     if(size > MSB32+offr){
9225                 if (same) {
9226                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9227                 } else {
9228                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9229                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9230                 }
9231     }
9232     if(offr != LSB)
9233                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9234
9235 }
9236
9237 /*-----------------------------------------------------------------*/
9238 /* genlshFour - shift four byte by a known amount != 0             */
9239 /*-----------------------------------------------------------------*/
9240 static void genlshFour (operand *result, operand *left, int shCount)
9241 {
9242     int size;
9243
9244     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9245     size = AOP_SIZE(result);
9246
9247     /* if shifting more that 3 bytes */
9248     if (shCount >= 24 ) {
9249         shCount -= 24;
9250         if (shCount)
9251             /* lowest order of left goes to the highest
9252             order of the destination */
9253             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9254         else
9255             movLeft2Result(left, LSB, result, MSB32);
9256
9257                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9258                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9259                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9260
9261         return;
9262     }
9263
9264     /* more than two bytes */
9265     else if ( shCount >= 16 ) {
9266         /* lower order two bytes goes to higher order two bytes */
9267         shCount -= 16;
9268         /* if some more remaining */
9269         if (shCount)
9270             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9271         else {
9272             movLeft2Result(left, MSB16, result, MSB32);
9273             movLeft2Result(left, LSB, result, MSB24);
9274         }
9275                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9276                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9277         return;
9278     }    
9279
9280     /* if more than 1 byte */
9281     else if ( shCount >= 8 ) {
9282         /* lower order three bytes goes to higher order  three bytes */
9283         shCount -= 8;
9284         if(size == 2){
9285             if(shCount)
9286                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9287             else
9288                 movLeft2Result(left, LSB, result, MSB16);
9289         }
9290         else{   /* size = 4 */
9291             if(shCount == 0){
9292                 movLeft2Result(left, MSB24, result, MSB32);
9293                 movLeft2Result(left, MSB16, result, MSB24);
9294                 movLeft2Result(left, LSB, result, MSB16);
9295                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9296             }
9297             else if(shCount == 1)
9298                 shiftLLong(left, result, MSB16);
9299             else{
9300                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9301                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9302                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9303                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9304             }
9305         }
9306     }
9307
9308     /* 1 <= shCount <= 7 */
9309     else if(shCount <= 3)
9310     { 
9311         shiftLLong(left, result, LSB);
9312         while(--shCount >= 1)
9313             shiftLLong(result, result, LSB);
9314     }
9315     /* 3 <= shCount <= 7, optimize */
9316     else{
9317         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9318         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9319         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9320     }
9321 }
9322
9323 /*-----------------------------------------------------------------*/
9324 /* genLeftShiftLiteral - left shifting by known count              */
9325 /*-----------------------------------------------------------------*/
9326 void pic16_genLeftShiftLiteral (operand *left,
9327                                  operand *right,
9328                                  operand *result,
9329                                  iCode *ic)
9330 {    
9331     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9332     int size;
9333
9334     FENTRY;
9335     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9336     pic16_freeAsmop(right,NULL,ic,TRUE);
9337
9338     pic16_aopOp(left,ic,FALSE);
9339     pic16_aopOp(result,ic,TRUE);
9340
9341     size = getSize(operandType(result));
9342
9343 #if VIEW_SIZE
9344     pic16_emitcode("; shift left ","result %d, left %d",size,
9345              AOP_SIZE(left));
9346 #endif
9347
9348     /* I suppose that the left size >= result size */
9349     if(shCount == 0){
9350         while(size--){
9351             movLeft2Result(left, size, result, size);
9352         }
9353     }
9354
9355     else if(shCount >= (size * 8))
9356         while(size--)
9357             pic16_aopPut(AOP(result),zero,size);
9358     else{
9359         switch (size) {
9360             case 1:
9361                 genlshOne (result,left,shCount);
9362                 break;
9363
9364             case 2:
9365             case 3:
9366                 genlshTwo (result,left,shCount);
9367                 break;
9368
9369             case 4:
9370                 genlshFour (result,left,shCount);
9371                 break;
9372         }
9373     }
9374     pic16_freeAsmop(left,NULL,ic,TRUE);
9375     pic16_freeAsmop(result,NULL,ic,TRUE);
9376 }
9377
9378 /*-----------------------------------------------------------------*
9379  * genMultiAsm - repeat assembly instruction for size of register.
9380  * if endian == 1, then the high byte (i.e base address + size of 
9381  * register) is used first else the low byte is used first;
9382  *-----------------------------------------------------------------*/
9383 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9384 {
9385
9386   int offset = 0;
9387
9388   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9389
9390   if(!reg)
9391     return;
9392
9393   if(!endian) {
9394     endian = 1;
9395   } else {
9396     endian = -1;
9397     offset = size-1;
9398   }
9399
9400   while(size--) {
9401     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9402     offset += endian;
9403   }
9404
9405 }
9406
9407 #if !(USE_GENERIC_SIGNED_SHIFT)
9408 /*-----------------------------------------------------------------*/
9409 /* genLeftShift - generates code for left shifting                 */
9410 /*-----------------------------------------------------------------*/
9411 static void genLeftShift (iCode *ic)
9412 {
9413   operand *left,*right, *result;
9414   int size, offset;
9415 //  char *l;
9416   symbol *tlbl , *tlbl1;
9417   pCodeOp *pctemp;
9418
9419   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9420
9421   right = IC_RIGHT(ic);
9422   left  = IC_LEFT(ic);
9423   result = IC_RESULT(ic);
9424
9425   pic16_aopOp(right,ic,FALSE);
9426
9427   /* if the shift count is known then do it 
9428      as efficiently as possible */
9429   if (AOP_TYPE(right) == AOP_LIT) {
9430     pic16_genLeftShiftLiteral (left,right,result,ic);
9431     return ;
9432   }
9433
9434   /* shift count is unknown then we have to form
9435    * a loop. Get the loop count in WREG : Note: we take
9436    * only the lower order byte since shifting
9437    * more than 32 bits make no sense anyway, ( the
9438    * largest size of an object can be only 32 bits ) */
9439   
9440   pic16_aopOp(left,ic,FALSE);
9441   pic16_aopOp(result,ic,FALSE);
9442
9443   /* now move the left to the result if they are not the
9444    * same, and if size > 1,
9445    * and if right is not same to result (!!!) -- VR */
9446   if (!pic16_sameRegs(AOP(left),AOP(result))
9447       && (AOP_SIZE(result) > 1)) {
9448
9449     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9450
9451     size = AOP_SIZE(result);
9452     offset=0;
9453     while (size--) {
9454
9455 #if 0
9456       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9457       if (*l == '@' && (IS_AOP_PREG(result))) {
9458
9459           pic16_emitcode("mov","a,%s",l);
9460           pic16_aopPut(AOP(result),"a",offset);
9461       } else
9462 #endif
9463       {
9464         /* we don't know if left is a literal or a register, take care -- VR */
9465         pic16_mov2f(AOP(result), AOP(left), offset);
9466       }
9467       offset++;
9468     }
9469   }
9470
9471   size = AOP_SIZE(result);
9472
9473   /* if it is only one byte then */
9474   if (size == 1) {
9475     if(optimized_for_speed) {
9476       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9477       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9478       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9479       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9480       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9481       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9482       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9483       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9484       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9485       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9486       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9487       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9488     } else {
9489
9490       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9491
9492       tlbl = newiTempLabel(NULL);
9493
9494 #if 1
9495       /* this is already done, why change it? */
9496       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9497                 pic16_mov2f(AOP(result), AOP(left), 0);
9498       }
9499 #endif
9500
9501       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9502       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9503       pic16_emitpLabel(tlbl->key);
9504       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9505       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9506       emitSKPC;
9507       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9508     }
9509     goto release ;
9510   }
9511     
9512   if (pic16_sameRegs(AOP(left),AOP(result))) {
9513
9514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9515     
9516     tlbl = newiTempLabel(NULL);
9517     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9518     genMultiAsm(POC_RRCF, result, size,1);
9519     pic16_emitpLabel(tlbl->key);
9520     genMultiAsm(POC_RLCF, result, size,0);
9521     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9522     emitSKPC;
9523     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9524     goto release;
9525   }
9526
9527   //tlbl = newiTempLabel(NULL);
9528   //offset = 0 ;   
9529   //tlbl1 = newiTempLabel(NULL);
9530
9531   //reAdjustPreg(AOP(result));    
9532     
9533   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9534   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9535   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9536   //MOVA(l);
9537   //pic16_emitcode("add","a,acc");         
9538   //pic16_aopPut(AOP(result),"a",offset++);
9539   //while (--size) {
9540   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9541   //  MOVA(l);
9542   //  pic16_emitcode("rlc","a");         
9543   //  pic16_aopPut(AOP(result),"a",offset++);
9544   //}
9545   //reAdjustPreg(AOP(result));
9546
9547   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9548   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9549
9550
9551   tlbl = newiTempLabel(NULL);
9552   tlbl1= newiTempLabel(NULL);
9553
9554   size = AOP_SIZE(result);
9555   offset = 1;
9556
9557   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9558
9559   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9560
9561   /* offset should be 0, 1 or 3 */
9562   
9563   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9564   emitSKPNZ;
9565   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9566
9567   pic16_emitpcode(POC_MOVWF, pctemp);
9568
9569
9570   pic16_emitpLabel(tlbl->key);
9571
9572   emitCLRC;
9573   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9574   while(--size)
9575     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9576
9577   pic16_emitpcode(POC_DECFSZ,  pctemp);
9578   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9579   pic16_emitpLabel(tlbl1->key);
9580
9581   pic16_popReleaseTempReg(pctemp,1);
9582
9583
9584  release:
9585   pic16_freeAsmop (right,NULL,ic,TRUE);
9586   pic16_freeAsmop(left,NULL,ic,TRUE);
9587   pic16_freeAsmop(result,NULL,ic,TRUE);
9588 }
9589 #endif
9590
9591
9592 #if 0
9593 #error old code (left here for reference)
9594 /*-----------------------------------------------------------------*/
9595 /* genLeftShift - generates code for left shifting                 */
9596 /*-----------------------------------------------------------------*/
9597 static void genLeftShift (iCode *ic)
9598 {
9599   operand *left,*right, *result;
9600   int size, offset;
9601   char *l;
9602   symbol *tlbl , *tlbl1;
9603   pCodeOp *pctemp;
9604
9605   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9606
9607   right = IC_RIGHT(ic);
9608   left  = IC_LEFT(ic);
9609   result = IC_RESULT(ic);
9610
9611   pic16_aopOp(right,ic,FALSE);
9612
9613   /* if the shift count is known then do it 
9614      as efficiently as possible */
9615   if (AOP_TYPE(right) == AOP_LIT) {
9616     pic16_genLeftShiftLiteral (left,right,result,ic);
9617     return ;
9618   }
9619
9620   /* shift count is unknown then we have to form 
9621      a loop get the loop count in B : Note: we take
9622      only the lower order byte since shifting
9623      more that 32 bits make no sense anyway, ( the
9624      largest size of an object can be only 32 bits ) */  
9625
9626     
9627   pic16_aopOp(left,ic,FALSE);
9628   pic16_aopOp(result,ic,FALSE);
9629
9630   /* now move the left to the result if they are not the
9631      same */
9632   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9633       AOP_SIZE(result) > 1) {
9634
9635     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9636
9637     size = AOP_SIZE(result);
9638     offset=0;
9639     while (size--) {
9640       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9641       if (*l == '@' && (IS_AOP_PREG(result))) {
9642
9643         pic16_emitcode("mov","a,%s",l);
9644         pic16_aopPut(AOP(result),"a",offset);
9645       } else {
9646
9647         /* we don't know if left is a literal or a register, take care -- VR */
9648         pic16_mov2f(AOP(result), AOP(left), offset);
9649       }
9650       offset++;
9651     }
9652   }
9653
9654   size = AOP_SIZE(result);
9655
9656   /* if it is only one byte then */
9657   if (size == 1) {
9658     if(optimized_for_speed) {
9659       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9660       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9661       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9662       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9663       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9664       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9665       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9666       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9667       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9668       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9669       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9670       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9671     } else {
9672
9673       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9674
9675       tlbl = newiTempLabel(NULL);
9676       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9677                 pic16_mov2f(AOP(result), AOP(left), 0);
9678                 
9679 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9680 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9681       }
9682
9683       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9684       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9685       pic16_emitpLabel(tlbl->key);
9686       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9687       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9688       emitSKPC;
9689       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9690     }
9691     goto release ;
9692   }
9693     
9694   if (pic16_sameRegs(AOP(left),AOP(result))) {
9695
9696     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9697     
9698     tlbl = newiTempLabel(NULL);
9699     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9700     genMultiAsm(POC_RRCF, result, size,1);
9701     pic16_emitpLabel(tlbl->key);
9702     genMultiAsm(POC_RLCF, result, size,0);
9703     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9704     emitSKPC;
9705     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9706     goto release;
9707   }
9708
9709   //tlbl = newiTempLabel(NULL);
9710   //offset = 0 ;   
9711   //tlbl1 = newiTempLabel(NULL);
9712
9713   //reAdjustPreg(AOP(result));    
9714     
9715   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9716   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9717   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9718   //MOVA(l);
9719   //pic16_emitcode("add","a,acc");         
9720   //pic16_aopPut(AOP(result),"a",offset++);
9721   //while (--size) {
9722   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9723   //  MOVA(l);
9724   //  pic16_emitcode("rlc","a");         
9725   //  pic16_aopPut(AOP(result),"a",offset++);
9726   //}
9727   //reAdjustPreg(AOP(result));
9728
9729   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9730   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9731
9732
9733   tlbl = newiTempLabel(NULL);
9734   tlbl1= newiTempLabel(NULL);
9735
9736   size = AOP_SIZE(result);
9737   offset = 1;
9738
9739   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9740
9741   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9742
9743   /* offset should be 0, 1 or 3 */
9744   
9745   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9746   emitSKPNZ;
9747   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9748
9749   pic16_emitpcode(POC_MOVWF, pctemp);
9750
9751
9752   pic16_emitpLabel(tlbl->key);
9753
9754   emitCLRC;
9755   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9756   while(--size)
9757     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9758
9759   pic16_emitpcode(POC_DECFSZ,  pctemp);
9760   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9761   pic16_emitpLabel(tlbl1->key);
9762
9763   pic16_popReleaseTempReg(pctemp,1);
9764
9765
9766  release:
9767   pic16_freeAsmop (right,NULL,ic,TRUE);
9768   pic16_freeAsmop(left,NULL,ic,TRUE);
9769   pic16_freeAsmop(result,NULL,ic,TRUE);
9770 }
9771 #endif
9772
9773 /*-----------------------------------------------------------------*/
9774 /* genrshOne - right shift a one byte quantity by known count      */
9775 /*-----------------------------------------------------------------*/
9776 static void genrshOne (operand *result, operand *left,
9777                        int shCount, int sign)
9778 {
9779     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9780     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9781 }
9782
9783 /*-----------------------------------------------------------------*/
9784 /* genrshTwo - right shift two bytes by known amount != 0          */
9785 /*-----------------------------------------------------------------*/
9786 static void genrshTwo (operand *result,operand *left,
9787                        int shCount, int sign)
9788 {
9789   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9790   /* if shCount >= 8 */
9791   if (shCount >= 8) {
9792     shCount -= 8 ;
9793     if (shCount)
9794       shiftR1Left2Result(left, MSB16, result, LSB,
9795                          shCount, sign);
9796     else
9797       movLeft2Result(left, MSB16, result, LSB);
9798
9799     pic16_addSign (result, 1, sign);
9800   }
9801
9802   /*  1 <= shCount <= 7 */
9803   else
9804     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9805 }
9806
9807 /*-----------------------------------------------------------------*/
9808 /* shiftRLong - shift right one long from left to result           */
9809 /* offl = LSB or MSB16                                             */
9810 /*-----------------------------------------------------------------*/
9811 static void shiftRLong (operand *left, int offl,
9812                         operand *result, int sign)
9813 {
9814     int size = AOP_SIZE(result);
9815     int same = pic16_sameRegs(AOP(left),AOP(result));
9816     int i;
9817     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9818
9819         if (same && (offl == MSB16)) { //shift one byte right
9820                 for(i=MSB16;i<size;i++) {
9821                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9822                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9823                 }
9824         }
9825
9826     if(sign)
9827                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9828         else
9829                 emitCLRC;
9830
9831         if (same) {
9832                 if (offl == LSB)
9833                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9834         } else {
9835         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9836         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9837         }
9838
9839     if(offl == MSB16) {
9840         /* add sign of "a" */
9841         pic16_addSign(result, MSB32, sign);
9842         }
9843
9844         if (same) {
9845         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9846         } else {
9847         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9848         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9849         }
9850         
9851         if (same) {
9852         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9853         } else {
9854         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9855         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9856         }
9857
9858         if (same) {
9859         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9860         } else {
9861         if(offl == LSB){
9862                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9863                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9864         }
9865         }
9866 }
9867
9868 /*-----------------------------------------------------------------*/
9869 /* genrshFour - shift four byte by a known amount != 0             */
9870 /*-----------------------------------------------------------------*/
9871 static void genrshFour (operand *result, operand *left,
9872                         int shCount, int sign)
9873 {
9874   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9875   /* if shifting more that 3 bytes */
9876   if(shCount >= 24 ) {
9877     shCount -= 24;
9878     if(shCount)
9879       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9880     else
9881       movLeft2Result(left, MSB32, result, LSB);
9882
9883     pic16_addSign(result, MSB16, sign);
9884   }
9885   else if(shCount >= 16){
9886     shCount -= 16;
9887     if(shCount)
9888       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9889     else{
9890       movLeft2Result(left, MSB24, result, LSB);
9891       movLeft2Result(left, MSB32, result, MSB16);
9892     }
9893     pic16_addSign(result, MSB24, sign);
9894   }
9895   else if(shCount >= 8){
9896     shCount -= 8;
9897     if(shCount == 1)
9898       shiftRLong(left, MSB16, result, sign);
9899     else if(shCount == 0){
9900       movLeft2Result(left, MSB16, result, LSB);
9901       movLeft2Result(left, MSB24, result, MSB16);
9902       movLeft2Result(left, MSB32, result, MSB24);
9903       pic16_addSign(result, MSB32, sign);
9904     }
9905     else{ //shcount >= 2
9906       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9907       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9908       /* the last shift is signed */
9909       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9910       pic16_addSign(result, MSB32, sign);
9911     }
9912   }
9913   else{   /* 1 <= shCount <= 7 */
9914     if(shCount <= 2){
9915       shiftRLong(left, LSB, result, sign);
9916       if(shCount == 2)
9917         shiftRLong(result, LSB, result, sign);
9918     }
9919     else{
9920       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9921       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9922       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9923     }
9924   }
9925 }
9926
9927 /*-----------------------------------------------------------------*/
9928 /* genRightShiftLiteral - right shifting by known count            */
9929 /*-----------------------------------------------------------------*/
9930 static void genRightShiftLiteral (operand *left,
9931                                   operand *right,
9932                                   operand *result,
9933                                   iCode *ic,
9934                                   int sign)
9935 {    
9936   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9937   int lsize,res_size;
9938
9939   pic16_freeAsmop(right,NULL,ic,TRUE);
9940
9941   pic16_aopOp(left,ic,FALSE);
9942   pic16_aopOp(result,ic,TRUE);
9943
9944   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9945
9946 #if VIEW_SIZE
9947   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9948                  AOP_SIZE(left));
9949 #endif
9950
9951   lsize = pic16_getDataSize(left);
9952   res_size = pic16_getDataSize(result);
9953   /* test the LEFT size !!! */
9954
9955   /* I suppose that the left size >= result size */
9956   if(shCount == 0){
9957     assert (res_size <= lsize);
9958     while (res_size--) {
9959       pic16_mov2f (AOP(result), AOP(left), res_size);
9960     } // for
9961   }
9962
9963   else if(shCount >= (lsize * 8)){
9964
9965     if(res_size == 1) {
9966       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9967       if(sign) {
9968         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9969         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9970       }
9971     } else {
9972
9973       if(sign) {
9974         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9975         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9976         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9977         while(res_size--)
9978           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9979
9980       } else {
9981
9982         while(res_size--)
9983           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9984       }
9985     }
9986   } else {
9987
9988     switch (res_size) {
9989     case 1:
9990       genrshOne (result,left,shCount,sign);
9991       break;
9992
9993     case 2:
9994       genrshTwo (result,left,shCount,sign);
9995       break;
9996
9997     case 4:
9998       genrshFour (result,left,shCount,sign);
9999       break;
10000     default :
10001       break;
10002     }
10003
10004   }
10005
10006   pic16_freeAsmop(left,NULL,ic,TRUE);
10007   pic16_freeAsmop(result,NULL,ic,TRUE);
10008 }
10009
10010 #if !(USE_GENERIC_SIGNED_SHIFT)
10011 /*-----------------------------------------------------------------*/
10012 /* genSignedRightShift - right shift of signed number              */
10013 /*-----------------------------------------------------------------*/
10014 static void genSignedRightShift (iCode *ic)
10015 {
10016   operand *right, *left, *result;
10017   int size, offset;
10018   //  char *l;
10019   symbol *tlbl, *tlbl1 ;
10020   pCodeOp *pctemp;
10021
10022   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10023
10024   /* we do it the hard way put the shift count in b
10025      and loop thru preserving the sign */
10026   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10027
10028   right = IC_RIGHT(ic);
10029   left  = IC_LEFT(ic);
10030   result = IC_RESULT(ic);
10031
10032   pic16_aopOp(right,ic,FALSE);  
10033   pic16_aopOp(left,ic,FALSE);
10034   pic16_aopOp(result,ic,FALSE);
10035
10036
10037   if ( AOP_TYPE(right) == AOP_LIT) {
10038     genRightShiftLiteral (left,right,result,ic,1);
10039     return ;
10040   }
10041   /* shift count is unknown then we have to form 
10042      a loop get the loop count in B : Note: we take
10043      only the lower order byte since shifting
10044      more that 32 bits make no sense anyway, ( the
10045      largest size of an object can be only 32 bits ) */  
10046
10047   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10048   //pic16_emitcode("inc","b");
10049   //pic16_freeAsmop (right,NULL,ic,TRUE);
10050   //pic16_aopOp(left,ic,FALSE);
10051   //pic16_aopOp(result,ic,FALSE);
10052
10053   /* now move the left to the result if they are not the
10054      same */
10055   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10056       AOP_SIZE(result) > 1) {
10057
10058     size = AOP_SIZE(result);
10059     offset=0;
10060     while (size--) { 
10061       /*
10062         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10063         if (*l == '@' && IS_AOP_PREG(result)) {
10064
10065         pic16_emitcode("mov","a,%s",l);
10066         pic16_aopPut(AOP(result),"a",offset);
10067         } else
10068         pic16_aopPut(AOP(result),l,offset);
10069       */
10070       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10071       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10072
10073       offset++;
10074     }
10075   }
10076
10077   /* mov the highest order bit to OVR */    
10078   tlbl = newiTempLabel(NULL);
10079   tlbl1= newiTempLabel(NULL);
10080
10081   size = AOP_SIZE(result);
10082   offset = size - 1;
10083
10084   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10085
10086   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10087
10088   /* offset should be 0, 1 or 3 */
10089   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10090   emitSKPNZ;
10091   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10092
10093   pic16_emitpcode(POC_MOVWF, pctemp);
10094
10095
10096   pic16_emitpLabel(tlbl->key);
10097
10098   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10099   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10100
10101   while(--size) {
10102     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10103   }
10104
10105   pic16_emitpcode(POC_DECFSZ,  pctemp);
10106   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10107   pic16_emitpLabel(tlbl1->key);
10108
10109   pic16_popReleaseTempReg(pctemp,1);
10110 #if 0
10111   size = AOP_SIZE(result);
10112   offset = size - 1;
10113   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10114   pic16_emitcode("rlc","a");
10115   pic16_emitcode("mov","ov,c");
10116   /* if it is only one byte then */
10117   if (size == 1) {
10118     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10119     MOVA(l);
10120     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10121     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10122     pic16_emitcode("mov","c,ov");
10123     pic16_emitcode("rrc","a");
10124     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10125     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10126     pic16_aopPut(AOP(result),"a",0);
10127     goto release ;
10128   }
10129
10130   reAdjustPreg(AOP(result));
10131   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10132   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10133   pic16_emitcode("mov","c,ov");
10134   while (size--) {
10135     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10136     MOVA(l);
10137     pic16_emitcode("rrc","a");         
10138     pic16_aopPut(AOP(result),"a",offset--);
10139   }
10140   reAdjustPreg(AOP(result));
10141   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10142   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10143
10144  release:
10145 #endif
10146
10147   pic16_freeAsmop(left,NULL,ic,TRUE);
10148   pic16_freeAsmop(result,NULL,ic,TRUE);
10149   pic16_freeAsmop(right,NULL,ic,TRUE);
10150 }
10151 #endif
10152
10153 #if !(USE_GENERIC_SIGNED_SHIFT)
10154 #warning This implementation of genRightShift() is incomplete!
10155 /*-----------------------------------------------------------------*/
10156 /* genRightShift - generate code for right shifting                */
10157 /*-----------------------------------------------------------------*/
10158 static void genRightShift (iCode *ic)
10159 {
10160     operand *right, *left, *result;
10161     sym_link *letype ;
10162     int size, offset;
10163     char *l;
10164     symbol *tlbl, *tlbl1 ;
10165
10166     /* if signed then we do it the hard way preserve the
10167     sign bit moving it inwards */
10168     letype = getSpec(operandType(IC_LEFT(ic)));
10169     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10170
10171     if (!SPEC_USIGN(letype)) {
10172         genSignedRightShift (ic);
10173         return ;
10174     }
10175
10176     /* signed & unsigned types are treated the same : i.e. the
10177     signed is NOT propagated inwards : quoting from the
10178     ANSI - standard : "for E1 >> E2, is equivalent to division
10179     by 2**E2 if unsigned or if it has a non-negative value,
10180     otherwise the result is implementation defined ", MY definition
10181     is that the sign does not get propagated */
10182
10183     right = IC_RIGHT(ic);
10184     left  = IC_LEFT(ic);
10185     result = IC_RESULT(ic);
10186
10187     pic16_aopOp(right,ic,FALSE);
10188
10189     /* if the shift count is known then do it 
10190     as efficiently as possible */
10191     if (AOP_TYPE(right) == AOP_LIT) {
10192         genRightShiftLiteral (left,right,result,ic, 0);
10193         return ;
10194     }
10195
10196     /* shift count is unknown then we have to form 
10197     a loop get the loop count in B : Note: we take
10198     only the lower order byte since shifting
10199     more that 32 bits make no sense anyway, ( the
10200     largest size of an object can be only 32 bits ) */  
10201
10202     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10203     pic16_emitcode("inc","b");
10204     pic16_aopOp(left,ic,FALSE);
10205     pic16_aopOp(result,ic,FALSE);
10206
10207     /* now move the left to the result if they are not the
10208     same */
10209     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10210         AOP_SIZE(result) > 1) {
10211
10212         size = AOP_SIZE(result);
10213         offset=0;
10214         while (size--) {
10215             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10216             if (*l == '@' && IS_AOP_PREG(result)) {
10217
10218                 pic16_emitcode("mov","a,%s",l);
10219                 pic16_aopPut(AOP(result),"a",offset);
10220             } else
10221                 pic16_aopPut(AOP(result),l,offset);
10222             offset++;
10223         }
10224     }
10225
10226     tlbl = newiTempLabel(NULL);
10227     tlbl1= newiTempLabel(NULL);
10228     size = AOP_SIZE(result);
10229     offset = size - 1;
10230
10231     /* if it is only one byte then */
10232     if (size == 1) {
10233
10234       tlbl = newiTempLabel(NULL);
10235       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10236         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10237         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10238       }
10239
10240       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10241       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10242       pic16_emitpLabel(tlbl->key);
10243       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10244       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10245       emitSKPC;
10246       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10247
10248       goto release ;
10249     }
10250
10251     reAdjustPreg(AOP(result));
10252     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10253     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10254     CLRC;
10255     while (size--) {
10256         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10257         MOVA(l);
10258         pic16_emitcode("rrc","a");         
10259         pic16_aopPut(AOP(result),"a",offset--);
10260     }
10261     reAdjustPreg(AOP(result));
10262
10263     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10264     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10265
10266 release:
10267     pic16_freeAsmop(left,NULL,ic,TRUE);
10268     pic16_freeAsmop (right,NULL,ic,TRUE);
10269     pic16_freeAsmop(result,NULL,ic,TRUE);
10270 }
10271 #endif
10272
10273 #if (USE_GENERIC_SIGNED_SHIFT)
10274 /*-----------------------------------------------------------------*/
10275 /* genGenericShift - generates code for left or right shifting     */
10276 /*-----------------------------------------------------------------*/
10277 static void genGenericShift (iCode *ic, int isShiftLeft) {
10278   operand *left,*right, *result;
10279   int offset;
10280   int sign, signedCount;
10281   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10282   PIC_OPCODE pos_shift, neg_shift;
10283
10284   FENTRY;
10285
10286   right = IC_RIGHT(ic);
10287   left  = IC_LEFT(ic);
10288   result = IC_RESULT(ic);
10289
10290   pic16_aopOp(right,ic,FALSE);
10291   pic16_aopOp(left,ic,FALSE);
10292   pic16_aopOp(result,ic,TRUE);
10293
10294   sign = !SPEC_USIGN(operandType (left));
10295   signedCount = !SPEC_USIGN(operandType (right));
10296
10297   /* if the shift count is known then do it 
10298      as efficiently as possible */
10299   if (AOP_TYPE(right) == AOP_LIT) {
10300     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10301     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10302     // we should modify right->aopu.aop_lit here!
10303     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10304     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10305     if (isShiftLeft)
10306       pic16_genLeftShiftLiteral (left,right,result,ic);
10307     else
10308       genRightShiftLiteral (left,right,result,ic, sign);
10309
10310     goto release;
10311   } // if (right is literal)
10312
10313   /* shift count is unknown then we have to form a loop.
10314    * Note: we take only the lower order byte since shifting
10315    * more than 32 bits make no sense anyway, ( the
10316    * largest size of an object can be only 32 bits )
10317    * Note: we perform arithmetic shifts if the left operand is
10318    * signed and we do an (effective) right shift, i. e. we
10319    * shift in the sign bit from the left. */
10320    
10321   label_complete = newiTempLabel ( NULL );
10322   label_loop_pos = newiTempLabel ( NULL );
10323   label_loop_neg = NULL;
10324   label_negative = NULL;
10325   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10326   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10327
10328   if (signedCount) {
10329     // additional labels needed
10330     label_loop_neg = newiTempLabel ( NULL );
10331     label_negative = newiTempLabel ( NULL );
10332   } // if
10333
10334   // copy source to result -- this will effectively truncate the left operand to the size of result!
10335   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10336   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10337   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10338     pic16_mov2f (AOP(result),AOP(left), offset);
10339   } // for
10340
10341   // if result is longer than left, fill with zeros (or sign)
10342   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10343     if (sign && AOP_SIZE(left) > 0) {
10344       // shift signed operand -- fill with sign
10345       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10346       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10347       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10348       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10349         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10350       } // for
10351     } else {
10352       // shift unsigned operand -- fill result with zeros
10353       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10354         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10355       } // for
10356     }
10357   } // if (size mismatch)
10358
10359   pic16_mov2w (AOP(right), 0);
10360   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10361   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10362   
10363 #if 0
10364   // perform a shift by one (shift count is positive)
10365   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10366   // 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])
10367   pic16_emitpLabel (label_loop_pos->key);
10368   emitCLRC;
10369   if (sign && (pos_shift == POC_RRCF)) {
10370     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10371     emitSETC;
10372   } // if
10373   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10374   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10375   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10376 #else
10377   // perform a shift by one (shift count is positive)
10378   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10379   // 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])
10380   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10381   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10382   emitCLRC;
10383   pic16_emitpLabel (label_loop_pos->key);
10384   if (sign && (pos_shift == POC_RRCF)) {
10385     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10386     emitSETC;
10387   } // if
10388   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10389   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10390   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10391   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10392 #endif
10393
10394   if (signedCount) {
10395     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10396
10397     pic16_emitpLabel (label_negative->key);
10398     // perform a shift by -1 (shift count is negative)
10399     // 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)
10400     emitCLRC;
10401     pic16_emitpLabel (label_loop_neg->key);
10402     if (sign && (neg_shift == POC_RRCF)) {
10403       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10404       emitSETC;
10405     } // if
10406     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10407     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10408     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10409     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10410   } // if (signedCount)
10411
10412   pic16_emitpLabel (label_complete->key);
10413
10414 release:
10415   pic16_freeAsmop (right,NULL,ic,TRUE);
10416   pic16_freeAsmop(left,NULL,ic,TRUE);
10417   pic16_freeAsmop(result,NULL,ic,TRUE);
10418 }
10419
10420 static void genLeftShift (iCode *ic) {
10421   genGenericShift (ic, 1);
10422 }
10423
10424 static void genRightShift (iCode *ic) {
10425   genGenericShift (ic, 0);
10426 }
10427 #endif
10428
10429
10430 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10431 void pic16_loadFSR0(operand *op, int lit)
10432 {
10433   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10434     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10435   } else {
10436     assert (!OP_SYMBOL(op)->remat);
10437     // set up FSR0 with address of result
10438     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10439     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10440   }
10441 }
10442
10443 /*----------------------------------------------------------------*/
10444 /* pic16_derefPtr - move one byte from the location ptr points to */
10445 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10446 /*                  to the location ptr points to (doWrite != 0)   */
10447 /*----------------------------------------------------------------*/
10448 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10449 {
10450   switch (p_type) {
10451     case FPOINTER:
10452     case POINTER:
10453       if (!fsr0_setup || !*fsr0_setup)
10454       {
10455         pic16_loadFSR0( ptr, 0 );
10456         if (fsr0_setup) *fsr0_setup = 1;
10457       }
10458       if (doWrite)
10459         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10460       else
10461         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10462       break;
10463
10464     case GPOINTER:
10465       if (AOP(ptr)->aopu.aop_reg[2]) {
10466         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10467         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10468         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10469         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10470         pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10471         pic16_callGenericPointerRW(doWrite, 1);
10472       } else {
10473         // data pointer (just 2 byte given)
10474         if (!fsr0_setup || !*fsr0_setup)
10475         {
10476           pic16_loadFSR0( ptr, 0 );
10477           if (fsr0_setup) *fsr0_setup = 1;
10478         }
10479         if (doWrite)
10480           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10481         else
10482           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10483       }
10484       break;
10485
10486     default:
10487       assert (0 && "invalid pointer type specified");
10488       break;
10489   }
10490 }
10491
10492 /*-----------------------------------------------------------------*/
10493 /* genUnpackBits - generates code for unpacking bits               */
10494 /*-----------------------------------------------------------------*/
10495 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10496 {    
10497   int shCnt ;
10498   sym_link *etype, *letype;
10499   int blen=0, bstr=0;
10500   int lbstr;
10501
10502     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10503     etype = getSpec(operandType(result));
10504     letype = getSpec(operandType(left));
10505     
10506 //    if(IS_BITFIELD(etype)) {
10507       blen = SPEC_BLEN(etype);
10508       bstr = SPEC_BSTR(etype);
10509 //    }
10510
10511     lbstr = SPEC_BSTR( letype );
10512
10513 #if 1
10514     if((blen == 1) && (bstr < 8)) {
10515       /* it is a single bit, so use the appropriate bit instructions */
10516       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10517
10518       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10519       
10520       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10521       if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10522         /* workaround to reduce the extra lfsr instruction */
10523         pic16_emitpcode(POC_BTFSC,
10524               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10525       } else {
10526         pic16_loadFSR0 (left, 0);
10527         pic16_emitpcode(POC_BTFSC,
10528               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10529       }
10530         
10531       pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10532
10533       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));      
10534       return;
10535     }
10536
10537 #endif
10538
10539         /* the following call to pic16_loadFSR0 is temporary until
10540          * optimization to handle single bit assignments is added
10541          * to the function. Until then use the old safe way! -- VR */
10542
10543     if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10544         // access symbol directly
10545         pic16_mov2w (AOP(left), 0);
10546     } else {
10547       pic16_derefPtr (left, ptype, 0, NULL);
10548     }
10549
10550         /* if we have bitdisplacement then it fits   */
10551         /* into this byte completely or if length is */
10552         /* less than a byte                          */
10553         if ((shCnt = SPEC_BSTR(etype)) || 
10554                 (SPEC_BLEN(etype) <= 8))  {
10555
10556                 /* shift right acc */
10557                 AccRsh(shCnt, 0);
10558
10559                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10560                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10561
10562 /* VR -- normally I would use the following, but since we use the hack,
10563  * to avoid the masking from AccRsh, why not mask it right now? */
10564
10565 /*
10566                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10567 */
10568
10569                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10570           return ;
10571         }
10572
10573
10574
10575         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10576         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10577         exit(-1);
10578
10579     return ;
10580 }
10581
10582
10583 static void genDataPointerGet(operand *left,
10584                               operand *result,
10585                               iCode *ic)
10586 {
10587   int size, offset = 0, leoffset=0 ;
10588
10589         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10590         pic16_aopOp(result, ic, TRUE);
10591
10592         FENTRY;
10593
10594         size = AOP_SIZE(result);
10595 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10596
10597
10598 #if 0
10599         /* The following tests may save a redudant movff instruction when
10600          * accessing unions */
10601          
10602         /* if they are the same */
10603         if (operandsEqu (left, result)) {
10604                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10605                 goto release;
10606         }
10607 #endif
10608
10609 #if 0
10610         /* if they are the same registers */
10611         if (pic16_sameRegs(AOP(left),AOP(result))) {
10612                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10613                 goto release;
10614         }
10615 #endif
10616
10617 #if 1
10618         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10619                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10620                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10621                 goto release;
10622         }
10623 #endif
10624
10625
10626 #if 0
10627         if ( AOP_TYPE(left) == AOP_PCODE) {
10628                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10629                                 AOP(left)->aopu.pcop->name,
10630                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10631                                 PCOR(AOP(left)->aopu.pcop)->instance:
10632                                 PCOI(AOP(left)->aopu.pcop)->offset);
10633         }
10634 #endif
10635
10636         if(AOP(left)->aopu.pcop->type == PO_DIR)
10637                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10638
10639         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10640
10641         while (size--) {
10642                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10643                 
10644 //              pic16_DumpOp("(result)",result);
10645                 if(is_LitAOp(AOP(result))) {
10646                         pic16_mov2w(AOP(left), offset); // patch 8
10647                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10648                 } else {
10649                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10650                                 pic16_popGet(AOP(left), offset), //patch 8
10651                                 pic16_popGet(AOP(result), offset)));
10652                 }
10653
10654                 offset++;
10655                 leoffset++;
10656         }
10657
10658 release:
10659     pic16_freeAsmop(result,NULL,ic,TRUE);
10660 }
10661
10662
10663
10664 /*-----------------------------------------------------------------*/
10665 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10666 /*-----------------------------------------------------------------*/
10667 static void genNearPointerGet (operand *left, 
10668                                operand *result, 
10669                                iCode *ic)
10670 {
10671 //  asmop *aop = NULL;
10672   //regs *preg = NULL ;
10673   sym_link *rtype, *retype;
10674   sym_link *ltype, *letype;
10675
10676     FENTRY;
10677     
10678     rtype = operandType(result);
10679     retype= getSpec(rtype);
10680     ltype = operandType(left);
10681     letype= getSpec(ltype);
10682     
10683     pic16_aopOp(left,ic,FALSE);
10684
10685 //    pic16_DumpOp("(left)",left);
10686 //    pic16_DumpOp("(result)",result);
10687
10688     /* if left is rematerialisable and
10689      * result is not bit variable type and
10690      * the left is pointer to data space i.e
10691      * lower 128 bytes of space */
10692     
10693     if (AOP_TYPE(left) == AOP_PCODE
10694       && !IS_BITFIELD(retype)
10695       && DCL_TYPE(ltype) == POINTER) {
10696
10697         genDataPointerGet (left,result,ic);
10698         pic16_freeAsmop(left, NULL, ic, TRUE);
10699         return ;
10700     }
10701     
10702     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10703     pic16_aopOp (result,ic,TRUE);
10704     
10705     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10706
10707 #if 1
10708     if(IS_BITFIELD( retype )
10709       && (SPEC_BLEN(operandType(result))==1)
10710     ) {
10711       iCode *nextic;
10712       pCodeOp *jop;
10713       int bitstrt, bytestrt;
10714
10715         /* if this is bitfield of size 1, see if we are checking the value
10716          * of a single bit in an if-statement,
10717          * if yes, then don't generate usual code, but execute the
10718          * genIfx directly -- VR */
10719
10720         nextic = ic->next;
10721
10722         /* CHECK: if next iCode is IFX
10723          * and current result operand is nextic's conditional operand
10724          * and current result operand live ranges ends at nextic's key number
10725          */
10726         if((nextic->op == IFX)
10727           && (result == IC_COND(nextic))
10728           && (OP_LIVETO(result) == nextic->seq)
10729           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10730           ) {
10731             /* everything is ok then */
10732             /* find a way to optimize the genIfx iCode */
10733
10734             bytestrt = SPEC_BSTR(operandType(result))/8;
10735             bitstrt = SPEC_BSTR(operandType(result))%8;
10736             
10737             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10738
10739             genIfxpCOpJump(nextic, jop);
10740             
10741             pic16_freeAsmop(left, NULL, ic, TRUE);
10742             pic16_freeAsmop(result, NULL, ic, TRUE);
10743             return;
10744         }
10745     }
10746 #endif
10747
10748     /* if bitfield then unpack the bits */
10749     if (IS_BITFIELD(letype)) 
10750       genUnpackBits (result, left, NULL, POINTER);
10751     else {
10752       /* we have can just get the values */
10753       int size = AOP_SIZE(result);
10754       int offset = 0;   
10755         
10756       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10757
10758       pic16_loadFSR0( left, 0 );
10759
10760       while(size--) {
10761         if(size) {
10762           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10763                 pic16_popGet(AOP(result), offset++)));
10764         } else {
10765           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10766                 pic16_popGet(AOP(result), offset++)));
10767         }
10768       }
10769     }
10770
10771 #if 0
10772     /* now some housekeeping stuff */
10773     if (aop) {
10774       /* we had to allocate for this iCode */
10775       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10776       pic16_freeAsmop(NULL,aop,ic,TRUE);
10777     } else { 
10778       /* we did not allocate which means left
10779        * already in a pointer register, then
10780        * if size > 0 && this could be used again
10781        * we have to point it back to where it 
10782        * belongs */
10783       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10784       if (AOP_SIZE(result) > 1
10785         && !OP_SYMBOL(left)->remat
10786         && ( OP_SYMBOL(left)->liveTo > ic->seq
10787             || ic->depth )) {
10788 //        int size = AOP_SIZE(result) - 1;
10789 //        while (size--)
10790 //          pic16_emitcode("dec","%s",rname);
10791         }
10792     }
10793 #endif
10794
10795     /* done */
10796     pic16_freeAsmop(left,NULL,ic,TRUE);
10797     pic16_freeAsmop(result,NULL,ic,TRUE);
10798 }
10799
10800 /*-----------------------------------------------------------------*/
10801 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10802 /*-----------------------------------------------------------------*/
10803 static void genPagedPointerGet (operand *left, 
10804                                operand *result, 
10805                                iCode *ic)
10806 {
10807     asmop *aop = NULL;
10808     regs *preg = NULL ;
10809     char *rname ;
10810     sym_link *rtype, *retype;    
10811
10812     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10813
10814     rtype = operandType(result);
10815     retype= getSpec(rtype);
10816     
10817     pic16_aopOp(left,ic,FALSE);
10818
10819   /* if the value is already in a pointer register
10820        then don't need anything more */
10821     if (!AOP_INPREG(AOP(left))) {
10822         /* otherwise get a free pointer register */
10823         aop = newAsmop(0);
10824         preg = getFreePtr(ic,&aop,FALSE);
10825         pic16_emitcode("mov","%s,%s",
10826                 preg->name,
10827                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10828         rname = preg->name ;
10829     } else
10830         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10831     
10832     pic16_freeAsmop(left,NULL,ic,TRUE);
10833     pic16_aopOp (result,ic,TRUE);
10834
10835     /* if bitfield then unpack the bits */
10836     if (IS_BITFIELD(retype)) 
10837         genUnpackBits (result,left,rname,PPOINTER);
10838     else {
10839         /* we have can just get the values */
10840         int size = AOP_SIZE(result);
10841         int offset = 0 ;        
10842         
10843         while (size--) {
10844             
10845             pic16_emitcode("movx","a,@%s",rname);
10846             pic16_aopPut(AOP(result),"a",offset);
10847             
10848             offset++ ;
10849             
10850             if (size)
10851                 pic16_emitcode("inc","%s",rname);
10852         }
10853     }
10854
10855     /* now some housekeeping stuff */
10856     if (aop) {
10857         /* we had to allocate for this iCode */
10858         pic16_freeAsmop(NULL,aop,ic,TRUE);
10859     } else { 
10860         /* we did not allocate which means left
10861            already in a pointer register, then
10862            if size > 0 && this could be used again
10863            we have to point it back to where it 
10864            belongs */
10865         if (AOP_SIZE(result) > 1 &&
10866             !OP_SYMBOL(left)->remat &&
10867             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10868               ic->depth )) {
10869             int size = AOP_SIZE(result) - 1;
10870             while (size--)
10871                 pic16_emitcode("dec","%s",rname);
10872         }
10873     }
10874
10875     /* done */
10876     pic16_freeAsmop(result,NULL,ic,TRUE);
10877     
10878         
10879 }
10880
10881 #if 0
10882 /* This code is not adjusted to PIC16 and fails utterly.
10883  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10884
10885 /*-----------------------------------------------------------------*/
10886 /* genFarPointerGet - gget value from far space                    */
10887 /*-----------------------------------------------------------------*/
10888 static void genFarPointerGet (operand *left,
10889                               operand *result, iCode *ic)
10890 {
10891     int size, offset ;
10892     sym_link *retype = getSpec(operandType(result));
10893
10894     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10895
10896     pic16_aopOp(left,ic,FALSE);
10897
10898     /* if the operand is already in dptr 
10899     then we do nothing else we move the value to dptr */
10900     if (AOP_TYPE(left) != AOP_STR) {
10901         /* if this is remateriazable */
10902         if (AOP_TYPE(left) == AOP_IMMD)
10903             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10904         else { /* we need to get it byte by byte */
10905             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10906             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10907             if (options.model == MODEL_FLAT24)
10908             {
10909                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10910             }
10911         }
10912     }
10913     /* so dptr know contains the address */
10914     pic16_freeAsmop(left,NULL,ic,TRUE);
10915     pic16_aopOp(result,ic,TRUE);
10916
10917     /* if bit then unpack */
10918     if (IS_BITFIELD(retype)) 
10919         genUnpackBits(result,left,"dptr",FPOINTER);
10920     else {
10921         size = AOP_SIZE(result);
10922         offset = 0 ;
10923
10924         while (size--) {
10925             pic16_emitcode("movx","a,@dptr");
10926             pic16_aopPut(AOP(result),"a",offset++);
10927             if (size)
10928                 pic16_emitcode("inc","dptr");
10929         }
10930     }
10931
10932     pic16_freeAsmop(result,NULL,ic,TRUE);
10933 }
10934 #endif
10935
10936 #if 0
10937 /*-----------------------------------------------------------------*/
10938 /* genCodePointerGet - get value from code space                  */
10939 /*-----------------------------------------------------------------*/
10940 static void genCodePointerGet (operand *left,
10941                                 operand *result, iCode *ic)
10942 {
10943     int size, offset ;
10944     sym_link *retype = getSpec(operandType(result));
10945
10946     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10947
10948     pic16_aopOp(left,ic,FALSE);
10949
10950     /* if the operand is already in dptr 
10951     then we do nothing else we move the value to dptr */
10952     if (AOP_TYPE(left) != AOP_STR) {
10953         /* if this is remateriazable */
10954         if (AOP_TYPE(left) == AOP_IMMD)
10955             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10956         else { /* we need to get it byte by byte */
10957             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10958             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10959             if (options.model == MODEL_FLAT24)
10960             {
10961                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10962             }
10963         }
10964     }
10965     /* so dptr know contains the address */
10966     pic16_freeAsmop(left,NULL,ic,TRUE);
10967     pic16_aopOp(result,ic,FALSE);
10968
10969     /* if bit then unpack */
10970     if (IS_BITFIELD(retype)) 
10971         genUnpackBits(result,left,"dptr",CPOINTER);
10972     else {
10973         size = AOP_SIZE(result);
10974         offset = 0 ;
10975
10976         while (size--) {
10977             pic16_emitcode("clr","a");
10978             pic16_emitcode("movc","a,@a+dptr");
10979             pic16_aopPut(AOP(result),"a",offset++);
10980             if (size)
10981                 pic16_emitcode("inc","dptr");
10982         }
10983     }
10984
10985     pic16_freeAsmop(result,NULL,ic,TRUE);
10986 }
10987 #endif
10988
10989 #if 0
10990 /*-----------------------------------------------------------------*/
10991 /* genGenPointerGet - gget value from generic pointer space        */
10992 /*-----------------------------------------------------------------*/
10993 static void genGenPointerGet (operand *left,
10994                               operand *result, iCode *ic)
10995 {
10996   int size, offset, lit;
10997   sym_link *retype = getSpec(operandType(result));
10998
10999         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11000         pic16_aopOp(left,ic,FALSE);
11001         pic16_aopOp(result,ic,FALSE);
11002         size = AOP_SIZE(result);
11003
11004         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11005
11006         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11007
11008                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11009                 // load FSR0 from immediate
11010                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11011
11012 //              pic16_loadFSR0( left );
11013
11014                 offset = 0;
11015                 while(size--) {
11016                         if(size) {
11017                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11018                         } else {
11019                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11020                         }
11021                         offset++;
11022                 }
11023                 goto release;
11024
11025         }
11026         else { /* we need to get it byte by byte */
11027                 // set up FSR0 with address from left
11028                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11029                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11030                 
11031                 offset = 0 ;
11032
11033                 while(size--) {
11034                         if(size) {
11035                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11036                         } else {
11037                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11038                         }
11039                         offset++;
11040                 }
11041                 goto release;
11042         }
11043
11044   /* if bit then unpack */
11045         if (IS_BITFIELD(retype)) 
11046                 genUnpackBits(result,left,"BAD",GPOINTER);
11047
11048         release:
11049         pic16_freeAsmop(left,NULL,ic,TRUE);
11050         pic16_freeAsmop(result,NULL,ic,TRUE);
11051
11052 }
11053 #endif
11054
11055
11056 /*-----------------------------------------------------------------*/
11057 /* genGenPointerGet - gget value from generic pointer space        */
11058 /*-----------------------------------------------------------------*/
11059 static void genGenPointerGet (operand *left,
11060                               operand *result, iCode *ic)
11061 {
11062   int size, offset, lit;
11063   sym_link *letype = getSpec(operandType(left));
11064
11065     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11066     pic16_aopOp(left,ic,FALSE);
11067     pic16_aopOp(result,ic,TRUE);
11068     size = AOP_SIZE(result);
11069
11070     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11071   
11072     /* if bit then unpack */
11073     if (IS_BITFIELD(letype)) {
11074       genUnpackBits(result,left,"BAD",GPOINTER);
11075       goto release;
11076     }
11077
11078     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11079
11080       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11081       // load FSR0 from immediate
11082       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11083
11084       werror(W_POSSBUG2, __FILE__, __LINE__);
11085
11086       offset = 0;
11087       while(size--) {
11088         if(size) {
11089           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11090         } else {
11091           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11092         }
11093         offset++;
11094       }
11095
11096       goto release;
11097
11098     } else { /* we need to get it byte by byte */
11099
11100       /* set up WREG:PRODL:FSR0L with address from left */
11101       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11102       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11103       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11104       
11105       pic16_callGenericPointerRW(0, size);
11106       
11107       assignResultValue(result, 1);
11108       
11109       goto release;
11110     }
11111
11112 release:
11113   pic16_freeAsmop(left,NULL,ic,TRUE);
11114   pic16_freeAsmop(result,NULL,ic,TRUE);
11115 }
11116
11117 /*-----------------------------------------------------------------*/
11118 /* genConstPointerGet - get value from const generic pointer space */
11119 /*-----------------------------------------------------------------*/
11120 static void genConstPointerGet (operand *left,
11121                                 operand *result, iCode *ic)
11122 {
11123   //sym_link *retype = getSpec(operandType(result));
11124   // symbol *albl = newiTempLabel(NULL);        // patch 15
11125   // symbol *blbl = newiTempLabel(NULL);        //
11126   // PIC_OPCODE poc;                            // patch 15
11127   int size;
11128   int offset = 0;
11129
11130   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11131   pic16_aopOp(left,ic,FALSE);
11132   pic16_aopOp(result,ic,TRUE);
11133   size = AOP_SIZE(result);
11134
11135   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11136
11137   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11138
11139   // set up table pointer
11140   if( (AOP_TYPE(left) == AOP_PCODE) 
11141       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11142           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11143     {
11144       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11145       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11146       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11147       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11148       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11149       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11150   } else {
11151     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11152     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11153     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11154   }
11155
11156   while(size--) {
11157     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11158     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11159     offset++;
11160   }
11161     
11162   pic16_freeAsmop(left,NULL,ic,TRUE);
11163   pic16_freeAsmop(result,NULL,ic,TRUE);
11164 }
11165
11166
11167 /*-----------------------------------------------------------------*/
11168 /* genPointerGet - generate code for pointer get                   */
11169 /*-----------------------------------------------------------------*/
11170 static void genPointerGet (iCode *ic)
11171 {
11172   operand *left, *result ;
11173   sym_link *type, *etype;
11174   int p_type;
11175
11176     FENTRY;
11177     
11178     left = IC_LEFT(ic);
11179     result = IC_RESULT(ic) ;
11180
11181     /* depending on the type of pointer we need to
11182     move it to the correct pointer register */
11183     type = operandType(left);
11184     etype = getSpec(type);
11185
11186 #if 0
11187     if (IS_PTR_CONST(type))
11188 #else
11189     if (IS_CODEPTR(type))
11190 #endif
11191       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11192
11193     /* if left is of type of pointer then it is simple */
11194     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11195       p_type = DCL_TYPE(type);
11196     else {
11197       /* we have to go by the storage class */
11198       p_type = PTR_TYPE(SPEC_OCLS(etype));
11199
11200       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11201
11202       if (SPEC_OCLS(etype)->codesp ) {
11203         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11204         //p_type = CPOINTER ;   
11205       } else
11206       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11207         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11208         /*p_type = FPOINTER ;*/ 
11209       } else
11210       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11211         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11212         /* p_type = PPOINTER; */
11213       } else
11214       if (SPEC_OCLS(etype) == idata ) {
11215         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11216         /* p_type = IPOINTER; */
11217       } else {
11218         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11219         /* p_type = POINTER ; */
11220       }
11221     }
11222
11223     /* now that we have the pointer type we assign
11224     the pointer values */
11225     switch (p_type) {
11226       case POINTER:     
11227       case FPOINTER:
11228       case IPOINTER:
11229         genNearPointerGet (left,result,ic);
11230         break;
11231
11232       case PPOINTER:
11233         genPagedPointerGet(left,result,ic);
11234         break;
11235
11236 #if 0
11237       /* PICs do not support FAR pointers... */
11238       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11239       case FPOINTER:
11240         genFarPointerGet (left,result,ic);
11241         break;
11242 #endif
11243
11244       case CPOINTER:
11245         genConstPointerGet (left,result,ic);
11246         //pic16_emitcodePointerGet (left,result,ic);
11247         break;
11248
11249       case GPOINTER:
11250 #if 0
11251       if (IS_PTR_CONST(type))
11252         genConstPointerGet (left,result,ic);
11253       else
11254 #endif
11255         genGenPointerGet (left,result,ic);
11256       break;
11257
11258     default:
11259       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11260               "genPointerGet: illegal pointer type");
11261     
11262     }
11263 }
11264
11265 /*-----------------------------------------------------------------*/
11266 /* genPackBits - generates code for packed bit storage             */
11267 /*-----------------------------------------------------------------*/
11268 static void genPackBits (sym_link    *etype , operand *result,
11269                          operand *right ,
11270                          char *rname, int p_type)
11271 {
11272   int shCnt = 0 ;
11273   int offset = 0  ;
11274   int rLen = 0 ;
11275   int blen, bstr ;   
11276   sym_link *retype;
11277
11278         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11279         blen = SPEC_BLEN(etype);
11280         bstr = SPEC_BSTR(etype);
11281
11282         retype = getSpec(operandType(right));
11283
11284         if(AOP_TYPE(right) == AOP_LIT) {
11285                 if((blen == 1) && (bstr < 8)) {
11286                   unsigned long lit;
11287                         /* it is a single bit, so use the appropriate bit instructions */
11288
11289                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11290
11291                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11292 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11293                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11294                                 /* workaround to reduce the extra lfsr instruction */
11295                                 if(lit) {
11296                                         pic16_emitpcode(POC_BSF,
11297                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11298                                 } else {
11299                                         pic16_emitpcode(POC_BCF,
11300                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11301                                 }
11302                         } else {
11303                                 pic16_loadFSR0(result, 0);
11304                                 if(lit) {
11305                                         pic16_emitpcode(POC_BSF,
11306                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11307                                 } else {
11308                                         pic16_emitpcode(POC_BCF,
11309                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11310                                 }
11311                         }
11312         
11313                   return;
11314                 }
11315                 /* move literal to W */
11316                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11317                 offset++;
11318         } else
11319         if(IS_BITFIELD(retype) 
11320           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11321           && (blen == 1)) {
11322           int rblen, rbstr;
11323
11324             rblen = SPEC_BLEN( retype );
11325             rbstr = SPEC_BSTR( retype );
11326             
11327
11328             if(IS_BITFIELD(etype)) {
11329               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11330               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11331             } else {
11332               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11333             }
11334             
11335             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11336             
11337             if(IS_BITFIELD(etype)) {
11338               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11339             } else {
11340               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11341             }
11342
11343             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11344             
11345             return;
11346         } else {
11347           /* move right to W */
11348           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11349         }
11350
11351         /* if the bit length is less than or   */
11352         /* it exactly fits a byte then         */
11353         if((shCnt=SPEC_BSTR(etype))
11354                 || SPEC_BLEN(etype) <= 8 )  {
11355                 int fsr0_setup = 0;
11356
11357                 if (blen != 8 || bstr != 0) {
11358                   // we need to combine the value with the old value
11359                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11360
11361           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11362                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11363                 
11364                   /* shift left acc */
11365                   AccLsh(shCnt);
11366
11367                   /* using PRODH as a temporary register here */
11368                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11369
11370                   if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11371                     /* access symbol directly */
11372                     pic16_mov2w (AOP(result), 0);
11373                   } else {
11374                     /* get old value */
11375                     pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11376                   }
11377 #if 1
11378                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11379                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11380                                         (unsigned char)(0xff >> (8-bstr))) ));
11381                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11382                 } // if (blen != 8 || bstr != 0)
11383
11384                 /* write new value back */
11385                 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11386                   pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11387                 } else {
11388                   pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11389                }
11390 #endif
11391
11392           return;
11393         }
11394
11395
11396 #if 0
11397         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11398         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11399         exit(-1);
11400 #endif
11401
11402
11403     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11404     rLen = SPEC_BLEN(etype)-8;
11405     
11406     /* now generate for lengths greater than one byte */
11407     while (1) {
11408         rLen -= 8 ;
11409         if (rLen <= 0 ) {
11410           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11411           break ;
11412         }
11413
11414         switch (p_type) {
11415             case POINTER:
11416                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11417                 break;
11418
11419 /*
11420             case FPOINTER:
11421                 MOVA(l);
11422                 pic16_emitcode("movx","@dptr,a");
11423                 break;
11424
11425             case GPOINTER:
11426                 MOVA(l);
11427                 DEBUGpic16_emitcode(";lcall","__gptrput");
11428                 break;  
11429 */
11430           default:
11431             assert(0);
11432         }   
11433
11434
11435         pic16_mov2w(AOP(right), offset++);
11436     }
11437
11438     /* last last was not complete */
11439     if (rLen)   {
11440         /* save the byte & read byte */
11441         switch (p_type) {
11442             case POINTER:
11443 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11444                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11445                 break;
11446
11447 /*
11448             case FPOINTER:
11449                 pic16_emitcode ("mov","b,a");
11450                 pic16_emitcode("movx","a,@dptr");
11451                 break;
11452
11453             case GPOINTER:
11454                 pic16_emitcode ("push","b");
11455                 pic16_emitcode ("push","acc");
11456                 pic16_emitcode ("lcall","__gptrget");
11457                 pic16_emitcode ("pop","b");
11458                 break;
11459 */
11460             default:
11461               assert(0);
11462         }
11463         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11464         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11465         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11466 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11467 //        pic16_emitcode ("orl","a,b");
11468     }
11469
11470 //    if (p_type == GPOINTER)
11471 //        pic16_emitcode("pop","b");
11472
11473     switch (p_type) {
11474
11475       case POINTER:
11476         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11477 //      pic16_emitcode("mov","@%s,a",rname);
11478         break;
11479 /*
11480       case FPOINTER:
11481         pic16_emitcode("movx","@dptr,a");
11482         break;
11483         
11484       case GPOINTER:
11485         DEBUGpic16_emitcode(";lcall","__gptrput");
11486         break;                  
11487 */
11488       default:
11489         assert(0);
11490     }
11491     
11492 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11493 }
11494 /*-----------------------------------------------------------------*/
11495 /* genDataPointerSet - remat pointer to data space                 */
11496 /*-----------------------------------------------------------------*/
11497 static void genDataPointerSet(operand *right,
11498                               operand *result,
11499                               iCode *ic)
11500 {
11501     int size, offset = 0, resoffset=0 ;
11502
11503     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11504     pic16_aopOp(right,ic,FALSE);
11505
11506     size = AOP_SIZE(right);
11507
11508 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11509
11510 #if 0
11511     if ( AOP_TYPE(result) == AOP_PCODE) {
11512       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11513               AOP(result)->aopu.pcop->name,
11514                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11515               PCOR(AOP(result)->aopu.pcop)->instance:
11516               PCOI(AOP(result)->aopu.pcop)->offset);
11517     }
11518 #endif
11519
11520         if(AOP(result)->aopu.pcop->type == PO_DIR)
11521                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11522
11523         while (size--) {
11524                 if (AOP_TYPE(right) == AOP_LIT) {
11525                   unsigned int lit;
11526
11527                     if(!IS_FLOAT(operandType( right )))
11528                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11529                     else {
11530                       union {
11531                         unsigned long lit_int;
11532                         float lit_float;
11533                       } info;
11534         
11535                         /* take care if literal is a float */
11536                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11537                         lit = info.lit_int;
11538                     }
11539
11540                     lit = lit >> (8*offset);
11541                     if(lit&0xff) {
11542                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11543                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11544                     } else {
11545                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11546                     }
11547                 } else {
11548                   pic16_mov2w(AOP(right), offset);
11549                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11550                 }
11551                 offset++;
11552                 resoffset++;
11553         }
11554
11555     pic16_freeAsmop(right,NULL,ic,TRUE);
11556 }
11557
11558
11559
11560 /*-----------------------------------------------------------------*/
11561 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11562 /*-----------------------------------------------------------------*/
11563 static void genNearPointerSet (operand *right,
11564                                operand *result, 
11565                                iCode *ic)
11566 {
11567   asmop *aop = NULL;
11568   sym_link *retype;
11569   sym_link *ptype = operandType(result);
11570   sym_link *resetype;
11571     
11572         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11573         retype= getSpec(operandType(right));
11574         resetype = getSpec(operandType(result));
11575   
11576         pic16_aopOp(result,ic,FALSE);
11577     
11578         /* if the result is rematerializable &
11579          * in data space & not a bit variable */
11580         
11581         /* and result is not a bit variable */
11582         if (AOP_TYPE(result) == AOP_PCODE
11583 //              && AOP_TYPE(result) == AOP_IMMD
11584                 && DCL_TYPE(ptype) == POINTER
11585                 && !IS_BITFIELD(retype)
11586                 && !IS_BITFIELD(resetype)) {
11587
11588                 genDataPointerSet (right,result,ic);
11589                 pic16_freeAsmop(result,NULL,ic,TRUE);
11590           return;
11591         }
11592
11593         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11594         pic16_aopOp(right,ic,FALSE);
11595         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11596
11597         /* if bitfield then unpack the bits */
11598         if (IS_BITFIELD(resetype)) {
11599                 genPackBits (resetype, result, right, NULL, POINTER);
11600         } else {
11601                 /* we have can just get the values */
11602           int size = AOP_SIZE(right);
11603           int offset = 0 ;    
11604
11605             pic16_loadFSR0(result, 0);
11606             
11607                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11608                 while (size--) {
11609                                 if (AOP_TYPE(right) == AOP_LIT) {
11610                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11611                                         if (size) {
11612                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11613                                         } else {
11614                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11615                                         }
11616                                 } else { // no literal
11617                                         if(size) {
11618                                                 pic16_emitpcode(POC_MOVFF,
11619                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11620                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11621                                         } else {
11622                                                 pic16_emitpcode(POC_MOVFF,
11623                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11624                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11625                                         }
11626                                 }
11627                         offset++;
11628                 }
11629         }
11630
11631         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11632         /* now some housekeeping stuff */
11633         if (aop) {
11634           /* we had to allocate for this iCode */
11635           pic16_freeAsmop(NULL,aop,ic,TRUE);
11636         } else { 
11637           /* we did not allocate which means left
11638            * already in a pointer register, then
11639            * if size > 0 && this could be used again
11640            * we have to point it back to where it 
11641            * belongs */
11642           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11643           if (AOP_SIZE(right) > 1
11644             && !OP_SYMBOL(result)->remat
11645             && ( OP_SYMBOL(result)->liveTo > ic->seq
11646             || ic->depth )) {
11647
11648               int size = AOP_SIZE(right) - 1;
11649
11650                 while (size--)
11651                   pic16_emitcode("decf","fsr0,f");
11652                   //pic16_emitcode("dec","%s",rname);
11653             }
11654         }
11655
11656     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11657     /* done */
11658 //release:
11659     pic16_freeAsmop(right,NULL,ic,TRUE);
11660     pic16_freeAsmop(result,NULL,ic,TRUE);
11661 }
11662
11663 /*-----------------------------------------------------------------*/
11664 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11665 /*-----------------------------------------------------------------*/
11666 static void genPagedPointerSet (operand *right,
11667                                operand *result, 
11668                                iCode *ic)
11669 {
11670     asmop *aop = NULL;
11671     regs *preg = NULL ;
11672     char *rname , *l;
11673     sym_link *retype;
11674        
11675     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11676
11677     retype= getSpec(operandType(right));
11678     
11679     pic16_aopOp(result,ic,FALSE);
11680     
11681     /* if the value is already in a pointer register
11682        then don't need anything more */
11683     if (!AOP_INPREG(AOP(result))) {
11684         /* otherwise get a free pointer register */
11685         aop = newAsmop(0);
11686         preg = getFreePtr(ic,&aop,FALSE);
11687         pic16_emitcode("mov","%s,%s",
11688                 preg->name,
11689                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11690         rname = preg->name ;
11691     } else
11692         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11693     
11694     pic16_freeAsmop(result,NULL,ic,TRUE);
11695     pic16_aopOp (right,ic,FALSE);
11696
11697     /* if bitfield then unpack the bits */
11698     if (IS_BITFIELD(retype)) 
11699         genPackBits (retype,result,right,rname,PPOINTER);
11700     else {
11701         /* we have can just get the values */
11702         int size = AOP_SIZE(right);
11703         int offset = 0 ;        
11704         
11705         while (size--) {
11706             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11707             
11708             MOVA(l);
11709             pic16_emitcode("movx","@%s,a",rname);
11710
11711             if (size)
11712                 pic16_emitcode("inc","%s",rname);
11713
11714             offset++;
11715         }
11716     }
11717     
11718     /* now some housekeeping stuff */
11719     if (aop) {
11720         /* we had to allocate for this iCode */
11721         pic16_freeAsmop(NULL,aop,ic,TRUE);
11722     } else { 
11723         /* we did not allocate which means left
11724            already in a pointer register, then
11725            if size > 0 && this could be used again
11726            we have to point it back to where it 
11727            belongs */
11728         if (AOP_SIZE(right) > 1 &&
11729             !OP_SYMBOL(result)->remat &&
11730             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11731               ic->depth )) {
11732             int size = AOP_SIZE(right) - 1;
11733             while (size--)
11734                 pic16_emitcode("dec","%s",rname);
11735         }
11736     }
11737
11738     /* done */
11739     pic16_freeAsmop(right,NULL,ic,TRUE);
11740     
11741         
11742 }
11743
11744 #if 0
11745 /* This code is not adjusted to PIC16 and fails utterly...
11746  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11747
11748 /*-----------------------------------------------------------------*/
11749 /* genFarPointerSet - set value from far space                     */
11750 /*-----------------------------------------------------------------*/
11751 static void genFarPointerSet (operand *right,
11752                               operand *result, iCode *ic)
11753 {
11754     int size, offset ;
11755     sym_link *retype = getSpec(operandType(right));
11756
11757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11758     pic16_aopOp(result,ic,FALSE);
11759
11760     /* if the operand is already in dptr 
11761     then we do nothing else we move the value to dptr */
11762     if (AOP_TYPE(result) != AOP_STR) {
11763         /* if this is remateriazable */
11764         if (AOP_TYPE(result) == AOP_IMMD)
11765             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11766         else { /* we need to get it byte by byte */
11767             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11768             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11769             if (options.model == MODEL_FLAT24)
11770             {
11771                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11772             }
11773         }
11774     }
11775     /* so dptr know contains the address */
11776     pic16_freeAsmop(result,NULL,ic,TRUE);
11777     pic16_aopOp(right,ic,FALSE);
11778
11779     /* if bit then unpack */
11780     if (IS_BITFIELD(retype)) 
11781         genPackBits(retype,result,right,"dptr",FPOINTER);
11782     else {
11783         size = AOP_SIZE(right);
11784         offset = 0 ;
11785
11786         while (size--) {
11787             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11788             MOVA(l);
11789             pic16_emitcode("movx","@dptr,a");
11790             if (size)
11791                 pic16_emitcode("inc","dptr");
11792         }
11793     }
11794
11795     pic16_freeAsmop(right,NULL,ic,TRUE);
11796 }
11797 #endif
11798
11799 /*-----------------------------------------------------------------*/
11800 /* genGenPointerSet - set value from generic pointer space         */
11801 /*-----------------------------------------------------------------*/
11802 #if 0
11803 static void genGenPointerSet (operand *right,
11804                               operand *result, iCode *ic)
11805 {
11806         int i, size, offset, lit;
11807         sym_link *retype = getSpec(operandType(right));
11808
11809         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11810
11811         pic16_aopOp(result,ic,FALSE);
11812         pic16_aopOp(right,ic,FALSE);
11813         size = AOP_SIZE(right);
11814         offset = 0;
11815
11816         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11817
11818         /* if the operand is already in dptr 
11819                 then we do nothing else we move the value to dptr */
11820         if (AOP_TYPE(result) != AOP_STR) {
11821                 /* if this is remateriazable */
11822                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11823                 // WARNING: anythig until "else" is untested!
11824                 if (AOP_TYPE(result) == AOP_IMMD) {
11825                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11826                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11827                         // load FSR0 from immediate
11828                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11829                         offset = 0;
11830                         while(size--) {
11831                                 if(size) {
11832                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11833                                 } else {
11834                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11835                                 }
11836                                 offset++;
11837                         }
11838                         goto release;
11839                 }
11840                 else { /* we need to get it byte by byte */
11841                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11842                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11843
11844                         // set up FSR0 with address of result
11845                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11846                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11847
11848                         /* hack hack! see if this the FSR. If so don't load W */
11849                         if(AOP_TYPE(right) != AOP_ACC) {
11850
11851                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11852
11853                                 if(AOP_TYPE(right) == AOP_LIT)
11854                                 {
11855                                         // copy literal
11856                                         // note: pic16_popGet handles sign extension
11857                                         for(i=0;i<size;i++) {
11858                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11859                                                 if(i < size-1)
11860                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11861                                                 else
11862                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11863                                         }
11864                                 } else {
11865                                         // copy regs
11866
11867                                         for(i=0;i<size;i++) {
11868                                                 if(i < size-1)
11869                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11870                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11871                                                 else
11872                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11873                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11874                                         }
11875                                 }
11876                                 goto release;
11877                         } 
11878                         // right = ACC
11879                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11880                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11881                         goto release;
11882         } // if (AOP_TYPE(result) != AOP_IMMD)
11883
11884         } // if (AOP_TYPE(result) != AOP_STR)
11885         /* so dptr know contains the address */
11886
11887
11888         /* if bit then unpack */
11889         if (IS_BITFIELD(retype)) 
11890                 genPackBits(retype,result,right,"dptr",GPOINTER);
11891         else {
11892                 size = AOP_SIZE(right);
11893                 offset = 0 ;
11894
11895                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11896
11897                 // set up FSR0 with address of result
11898                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11899                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11900         
11901                 while (size--) {
11902                         if (AOP_TYPE(right) == AOP_LIT) {
11903                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11904                                 if (size) {
11905                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11906                                 } else {
11907                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11908                                 }
11909                         } else { // no literal
11910                                 if(size) {
11911                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11912                                 } else {
11913                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11914                                 }
11915                         }
11916                         offset++;
11917                 }
11918         }
11919
11920         release:
11921         pic16_freeAsmop(right,NULL,ic,TRUE);
11922         pic16_freeAsmop(result,NULL,ic,TRUE);
11923 }
11924 #endif
11925
11926 static void genGenPointerSet (operand *right,
11927                               operand *result, iCode *ic)
11928 {
11929   int size;
11930   sym_link *retype = getSpec(operandType(result));
11931
11932     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11933
11934     pic16_aopOp(result,ic,FALSE);
11935     pic16_aopOp(right,ic,FALSE);
11936     size = AOP_SIZE(right);
11937
11938     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11939
11940
11941     /* if bit then unpack */
11942     if (IS_BITFIELD(retype)) {
11943 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11944       genPackBits(retype,result,right,"dptr",GPOINTER);
11945       goto release;
11946     }
11947
11948     size = AOP_SIZE(right);
11949
11950     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11951
11952
11953     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11954
11955     /* value of right+0 is placed on stack, which will be retrieved
11956      * by the support function this restoring the stack. The important
11957      * thing is that there is no need to manually restore stack pointer
11958      * here */
11959     pushaop(AOP(right), 0);
11960 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11961     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11962     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11963     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11964     
11965     /* load address to write to in WREG:FSR0H:FSR0L */
11966     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11967                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11968     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11969                                 pic16_popCopyReg(&pic16_pc_prodl)));
11970     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11971     
11972     pic16_callGenericPointerRW(1, size);
11973
11974 release:
11975     pic16_freeAsmop(right,NULL,ic,TRUE);
11976     pic16_freeAsmop(result,NULL,ic,TRUE);
11977 }
11978
11979 /*-----------------------------------------------------------------*/
11980 /* genPointerSet - stores the value into a pointer location        */
11981 /*-----------------------------------------------------------------*/
11982 static void genPointerSet (iCode *ic)
11983 {    
11984   operand *right, *result ;
11985   sym_link *type, *etype;
11986   int p_type;
11987
11988     FENTRY;
11989
11990     right = IC_RIGHT(ic);
11991     result = IC_RESULT(ic) ;
11992
11993     /* depending on the type of pointer we need to
11994     move it to the correct pointer register */
11995     type = operandType(result);
11996     etype = getSpec(type);
11997     
11998     /* if left is of type of pointer then it is simple */
11999     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12000         p_type = DCL_TYPE(type);
12001     }
12002     else {
12003         /* we have to go by the storage class */
12004         p_type = PTR_TYPE(SPEC_OCLS(etype));
12005
12006 /*      if (SPEC_OCLS(etype)->codesp ) { */
12007 /*          p_type = CPOINTER ;  */
12008 /*      } */
12009 /*      else */
12010 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12011 /*              p_type = FPOINTER ; */
12012 /*          else */
12013 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12014 /*                  p_type = PPOINTER ; */
12015 /*              else */
12016 /*                  if (SPEC_OCLS(etype) == idata ) */
12017 /*                      p_type = IPOINTER ; */
12018 /*                  else */
12019 /*                      p_type = POINTER ; */
12020     }
12021
12022     /* now that we have the pointer type we assign
12023     the pointer values */
12024     switch (p_type) {
12025       case POINTER:
12026       case FPOINTER:
12027       case IPOINTER:
12028         genNearPointerSet (right,result,ic);
12029         break;
12030
12031       case PPOINTER:
12032         genPagedPointerSet (right,result,ic);
12033         break;
12034
12035 #if 0
12036       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12037       case FPOINTER:
12038         genFarPointerSet (right,result,ic);
12039         break;
12040 #endif
12041         
12042       case GPOINTER:
12043         genGenPointerSet (right,result,ic);
12044         break;
12045
12046       default:
12047         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12048           "genPointerSet: illegal pointer type");
12049     }
12050 }
12051
12052 /*-----------------------------------------------------------------*/
12053 /* genIfx - generate code for Ifx statement                        */
12054 /*-----------------------------------------------------------------*/
12055 static void genIfx (iCode *ic, iCode *popIc)
12056 {
12057   operand *cond = IC_COND(ic);
12058   int isbit =0;
12059
12060     FENTRY;
12061
12062     pic16_aopOp(cond,ic,FALSE);
12063
12064     /* get the value into acc */
12065     if (AOP_TYPE(cond) != AOP_CRY)
12066       pic16_toBoolean(cond);
12067     else
12068       isbit = 1;
12069     /* the result is now in the accumulator */
12070     pic16_freeAsmop(cond,NULL,ic,TRUE);
12071
12072     /* if there was something to be popped then do it */
12073     if (popIc)
12074       genIpop(popIc);
12075
12076     /* if the condition is  a bit variable */
12077     if (isbit && IS_ITEMP(cond) && 
12078         SPIL_LOC(cond)) {
12079       genIfxJump(ic,"c");
12080       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12081     } else {
12082       if (isbit && !IS_ITEMP(cond))
12083         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12084         else
12085         genIfxJump(ic,"a");
12086     }
12087     ic->generated = 1;
12088 }
12089
12090 /*-----------------------------------------------------------------*/
12091 /* genAddrOf - generates code for address of                       */
12092 /*-----------------------------------------------------------------*/
12093 static void genAddrOf (iCode *ic)
12094 {
12095   operand *result, *left;
12096   int size;
12097   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12098   pCodeOp *pcop0, *pcop1, *pcop2;
12099
12100     FENTRY;
12101
12102     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12103
12104     sym = OP_SYMBOL( IC_LEFT(ic) );
12105     
12106     if(sym->onStack) {
12107       /* get address of symbol on stack */
12108       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12109 #if 0
12110       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12111                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12112 #endif
12113
12114       // operands on stack are accessible via "FSR2 + index" with index
12115       // starting at 2 for arguments and growing from 0 downwards for
12116       // local variables (index == 0 is not assigned so we add one here)
12117       {
12118         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12119         if (soffs <= 0) {
12120           assert (soffs < 0);
12121           soffs++;
12122         } // if
12123         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12124         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12125         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12126         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12127         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12128         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12129         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12130       }
12131
12132       goto release;
12133     }
12134         
12135 //      if(pic16_debug_verbose) {
12136 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12137 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12138 //      }
12139         
12140     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12141     size = AOP_SIZE(IC_RESULT(ic));
12142
12143     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12144     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12145     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12146         
12147     if (size == 3) {
12148       pic16_emitpcode(POC_MOVLW, pcop0);
12149       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12150       pic16_emitpcode(POC_MOVLW, pcop1);
12151       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12152       pic16_emitpcode(POC_MOVLW, pcop2);
12153       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12154     } else
12155     if (size == 2) {
12156       pic16_emitpcode(POC_MOVLW, pcop0);
12157       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12158       pic16_emitpcode(POC_MOVLW, pcop1);
12159     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12160     } else {
12161       pic16_emitpcode(POC_MOVLW, pcop0);
12162       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12163     }
12164
12165     pic16_freeAsmop(left, NULL, ic, FALSE);
12166 release:
12167     pic16_freeAsmop(result,NULL,ic,TRUE);
12168 }
12169
12170
12171 #if 0
12172 /*-----------------------------------------------------------------*/
12173 /* genFarFarAssign - assignment when both are in far space         */
12174 /*-----------------------------------------------------------------*/
12175 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12176 {
12177     int size = AOP_SIZE(right);
12178     int offset = 0;
12179     char *l ;
12180     /* first push the right side on to the stack */
12181     while (size--) {
12182         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12183         MOVA(l);
12184         pic16_emitcode ("push","acc");
12185     }
12186     
12187     pic16_freeAsmop(right,NULL,ic,FALSE);
12188     /* now assign DPTR to result */
12189     pic16_aopOp(result,ic,FALSE);
12190     size = AOP_SIZE(result);
12191     while (size--) {
12192         pic16_emitcode ("pop","acc");
12193         pic16_aopPut(AOP(result),"a",--offset);
12194     }
12195     pic16_freeAsmop(result,NULL,ic,FALSE);
12196         
12197 }
12198 #endif
12199
12200 /*-----------------------------------------------------------------*/
12201 /* genAssign - generate code for assignment                        */
12202 /*-----------------------------------------------------------------*/
12203 static void genAssign (iCode *ic)
12204 {
12205   operand *result, *right;
12206   int size, offset,know_W;
12207   unsigned long lit = 0L;
12208
12209   result = IC_RESULT(ic);
12210   right  = IC_RIGHT(ic) ;
12211
12212   FENTRY;
12213   
12214   /* if they are the same */
12215   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12216     return ;
12217
12218   /* reversed order operands are aopOp'ed so that result operand
12219    * is effective in case right is a stack symbol. This maneauver
12220    * allows to use the _G.resDirect flag later */
12221   pic16_aopOp(result,ic,TRUE);
12222   pic16_aopOp(right,ic,FALSE);
12223
12224   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12225
12226   /* if they are the same registers */
12227   if (pic16_sameRegs(AOP(right),AOP(result)))
12228     goto release;
12229
12230   /* if the result is a bit */
12231   if (AOP_TYPE(result) == AOP_CRY) {
12232     /* if the right size is a literal then
12233        we know what the value is */
12234     if (AOP_TYPE(right) == AOP_LIT) {
12235           
12236       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12237                   pic16_popGet(AOP(result),0));
12238
12239       if (((int) operandLitValue(right))) 
12240         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12241                        AOP(result)->aopu.aop_dir,
12242                        AOP(result)->aopu.aop_dir);
12243       else
12244         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12245                        AOP(result)->aopu.aop_dir,
12246                        AOP(result)->aopu.aop_dir);
12247       goto release;
12248     }
12249
12250     /* the right is also a bit variable */
12251     if (AOP_TYPE(right) == AOP_CRY) {
12252       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12253       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12254       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12255
12256       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12257                      AOP(result)->aopu.aop_dir,
12258                      AOP(result)->aopu.aop_dir);
12259       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12260                      AOP(right)->aopu.aop_dir,
12261                      AOP(right)->aopu.aop_dir);
12262       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12263                      AOP(result)->aopu.aop_dir,
12264                      AOP(result)->aopu.aop_dir);
12265       goto release ;
12266     }
12267
12268     /* we need to or */
12269     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12270     pic16_toBoolean(right);
12271     emitSKPZ;
12272     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12273     //pic16_aopPut(AOP(result),"a",0);
12274     goto release ;
12275   }
12276
12277   /* bit variables done */
12278   /* general case */
12279   size = AOP_SIZE(result);
12280   offset = 0 ;
12281
12282   if(AOP_TYPE(right) == AOP_LIT) {
12283         if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12284                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12285         else{
12286            union {
12287               unsigned long lit_int;
12288               float lit_float;
12289             } info;
12290         
12291
12292               if(IS_FIXED16X16(operandType(right))) {
12293                 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12294               } else {
12295                 /* take care if literal is a float */
12296                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12297                 lit = info.lit_int;
12298               }
12299         }
12300   }
12301
12302 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12303 //                      sizeof(unsigned long int), sizeof(float));
12304
12305
12306   if (AOP_TYPE(right) == AOP_REG) {
12307     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12308     while (size--) {
12309       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12310     } // while
12311     goto release;
12312   }
12313
12314   /* when do we have to read the program memory?
12315    * - if right itself is a symbol in code space
12316    *   (we don't care what it points to if it's a pointer)
12317    * - AND right is not a function (we would want its address)
12318    */
12319   if(AOP_TYPE(right) != AOP_LIT
12320         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12321         && !IS_FUNC(OP_SYM_TYPE(right))
12322         && !IS_ITEMP(right))
12323   {
12324         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12325         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12326
12327         // set up table pointer
12328         if(is_LitOp(right)) {
12329 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12330                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12331                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12332                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12333                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12334                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12335                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12336         } else {
12337 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12338                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12339                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12340                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12341                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12342                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12343                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12344         }
12345
12346         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12347         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12348         while(size--) {
12349                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12350                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12351                         pic16_popGet(AOP(result),offset)));
12352                 offset++;
12353         }
12354
12355         /* FIXME: for pointers we need to extend differently (according
12356          * to pointer type DATA/CODE/EEPROM/... :*/
12357         size = getSize(OP_SYM_TYPE(right));
12358         if(AOP_SIZE(result) > size) {
12359                 size = AOP_SIZE(result) - size;
12360                 while(size--) {
12361                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12362                         offset++;
12363                 }
12364         }
12365         goto release;
12366   }
12367
12368
12369
12370 #if 0
12371 /* VR - What is this?! */
12372   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12373     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12374     if(aopIdx(AOP(result),0) == 4) {
12375
12376       /* this is a workaround to save value of right into wreg too,
12377        * value of wreg is going to be used later */
12378       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12379       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12380       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12381       goto release;
12382     } else
12383 //      assert(0);
12384       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12385   }
12386 #endif
12387
12388   know_W=-1;
12389   while (size--) {
12390   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12391     if(AOP_TYPE(right) == AOP_LIT) {
12392       if(lit&0xff) {
12393         if(know_W != (lit&0xff))
12394           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12395         know_W = lit&0xff;
12396         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12397       } else
12398         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12399
12400       lit >>= 8;
12401
12402     } else if (AOP_TYPE(right) == AOP_CRY) {
12403       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12404       if(offset == 0) {
12405         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12406         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12407         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12408       }
12409     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12410         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12411         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12412     } else {
12413       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12414
12415       if(!_G.resDirect)         /* use this aopForSym feature */
12416         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12417     }
12418             
12419     offset++;
12420   }
12421   
12422  release:
12423   pic16_freeAsmop (right,NULL,ic,FALSE);
12424   pic16_freeAsmop (result,NULL,ic,TRUE);
12425 }   
12426
12427 /*-----------------------------------------------------------------*/
12428 /* genJumpTab - generates code for jump table                       */
12429 /*-----------------------------------------------------------------*/
12430 static void genJumpTab (iCode *ic)
12431 {
12432   symbol *jtab;
12433   char *l;
12434   pCodeOp *jt_offs;
12435   pCodeOp *jt_offs_hi;
12436   pCodeOp *jt_label;
12437
12438     FENTRY;
12439
12440     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12441     /* get the condition into accumulator */
12442     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12443     MOVA(l);
12444     /* multiply by three */
12445     pic16_emitcode("add","a,acc");
12446     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12447
12448     jtab = newiTempLabel(NULL);
12449     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12450     pic16_emitcode("jmp","@a+dptr");
12451     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12452
12453 #if 0
12454     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12455     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12456     emitSKPNC;
12457     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12458     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12459     pic16_emitpLabel(jtab->key);
12460
12461 #else
12462
12463     jt_offs = pic16_popGetTempReg(0);
12464     jt_offs_hi = pic16_popGetTempReg(1);
12465     jt_label = pic16_popGetLabel (jtab->key);
12466     //fprintf (stderr, "Creating jump table...\n");
12467
12468     // calculate offset into jump table (idx * sizeof (GOTO))
12469     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12470     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12471     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12472     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12473     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12474     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12475     pic16_emitpcode(POC_MOVWF , jt_offs);
12476
12477     // prepare PCLATx (set to first entry in jump table)
12478     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12479     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12480     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12481     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12482     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12483
12484     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12485     pic16_emitpcode(POC_ADDWF , jt_offs);
12486     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12487     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12488     emitSKPNC;
12489     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12490
12491     // release temporaries and prepare jump into table (new PCL --> WREG)
12492     pic16_emitpcode(POC_MOVFW , jt_offs);
12493     pic16_popReleaseTempReg (jt_offs_hi, 1);
12494     pic16_popReleaseTempReg (jt_offs, 0);
12495
12496     // jump into the table
12497     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12498
12499     pic16_emitpLabelFORCE(jtab->key);
12500 #endif
12501
12502     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12503 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12504
12505     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12506     /* now generate the jump labels */
12507     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12508          jtab = setNextItem(IC_JTLABELS(ic))) {
12509 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12510         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12511         
12512     }
12513     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12514
12515 }
12516
12517 /*-----------------------------------------------------------------*/
12518 /* genMixedOperation - gen code for operators between mixed types  */
12519 /*-----------------------------------------------------------------*/
12520 /*
12521   TSD - Written for the PIC port - but this unfortunately is buggy.
12522   This routine is good in that it is able to efficiently promote 
12523   types to different (larger) sizes. Unfortunately, the temporary
12524   variables that are optimized out by this routine are sometimes
12525   used in other places. So until I know how to really parse the 
12526   iCode tree, I'm going to not be using this routine :(.
12527 */
12528 static int genMixedOperation (iCode *ic)
12529 {
12530 #if 0
12531   operand *result = IC_RESULT(ic);
12532   sym_link *ctype = operandType(IC_LEFT(ic));
12533   operand *right = IC_RIGHT(ic);
12534   int ret = 0;
12535   int big,small;
12536   int offset;
12537
12538   iCode *nextic;
12539   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12540
12541   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12542
12543   nextic = ic->next;
12544   if(!nextic)
12545     return 0;
12546
12547   nextright = IC_RIGHT(nextic);
12548   nextleft  = IC_LEFT(nextic);
12549   nextresult = IC_RESULT(nextic);
12550
12551   pic16_aopOp(right,ic,FALSE);
12552   pic16_aopOp(result,ic,FALSE);
12553   pic16_aopOp(nextright,  nextic, FALSE);
12554   pic16_aopOp(nextleft,   nextic, FALSE);
12555   pic16_aopOp(nextresult, nextic, FALSE);
12556
12557   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12558
12559     operand *t = right;
12560     right = nextright;
12561     nextright = t; 
12562
12563     pic16_emitcode(";remove right +","");
12564
12565   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12566 /*
12567     operand *t = right;
12568     right = nextleft;
12569     nextleft = t; 
12570 */
12571     pic16_emitcode(";remove left +","");
12572   } else
12573     return 0;
12574
12575   big = AOP_SIZE(nextleft);
12576   small = AOP_SIZE(nextright);
12577
12578   switch(nextic->op) {
12579
12580   case '+':
12581     pic16_emitcode(";optimize a +","");
12582     /* if unsigned or not an integral type */
12583     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12584       pic16_emitcode(";add a bit to something","");
12585     } else {
12586
12587       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12588
12589       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12590         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12591         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12592       } else
12593         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12594
12595       offset = 0;
12596       while(--big) {
12597
12598         offset++;
12599
12600         if(--small) {
12601           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12602             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12603             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12604           }
12605
12606           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12607           emitSKPNC;
12608           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12609                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12610                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12611           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12612           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12613
12614         } else {
12615           pic16_emitcode("rlf","known_zero,w");
12616
12617           /*
12618             if right is signed
12619               btfsc  right,7
12620                addlw ff
12621           */
12622           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12623             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12624             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12625           } else {
12626             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12627           }
12628         }
12629       }
12630       ret = 1;
12631     }
12632   }
12633   ret = 1;
12634
12635 release:
12636   pic16_freeAsmop(right,NULL,ic,TRUE);
12637   pic16_freeAsmop(result,NULL,ic,TRUE);
12638   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12639   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12640   if(ret)
12641     nextic->generated = 1;
12642
12643   return ret;
12644 #else
12645   return 0;
12646 #endif
12647 }
12648 /*-----------------------------------------------------------------*/
12649 /* genCast - gen code for casting                                  */
12650 /*-----------------------------------------------------------------*/
12651 static void genCast (iCode *ic)
12652 {
12653   operand *result = IC_RESULT(ic);
12654   sym_link *ctype = operandType(IC_LEFT(ic));
12655   sym_link *rtype = operandType(IC_RIGHT(ic));
12656   sym_link *restype = operandType(IC_RESULT(ic));
12657   operand *right = IC_RIGHT(ic);
12658   int size, offset ;
12659
12660
12661     FENTRY;
12662
12663         /* if they are equivalent then do nothing */
12664 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12665 //              return ;
12666
12667         pic16_aopOp(result,ic,FALSE);
12668         pic16_aopOp(right,ic,FALSE) ;
12669
12670         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12671
12672
12673         /* if the result is a bit */
12674         if (AOP_TYPE(result) == AOP_CRY) {
12675         
12676                 /* if the right size is a literal then
12677                  * we know what the value is */
12678                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12679
12680                 if (AOP_TYPE(right) == AOP_LIT) {
12681                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12682                                 pic16_popGet(AOP(result),0));
12683
12684                         if (((int) operandLitValue(right))) 
12685                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12686                                         AOP(result)->aopu.aop_dir,
12687                                         AOP(result)->aopu.aop_dir);
12688                         else
12689                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12690                                         AOP(result)->aopu.aop_dir,
12691                                         AOP(result)->aopu.aop_dir);
12692                         goto release;
12693                 }
12694
12695                 /* the right is also a bit variable */
12696                 if (AOP_TYPE(right) == AOP_CRY) {
12697                         emitCLRC;
12698                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12699
12700                         pic16_emitcode("clrc","");
12701                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12702                                 AOP(right)->aopu.aop_dir,
12703                                 AOP(right)->aopu.aop_dir);
12704                         pic16_aopPut(AOP(result),"c",0);
12705                         goto release ;
12706                 }
12707
12708                 /* we need to or */
12709                 if (AOP_TYPE(right) == AOP_REG) {
12710                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12711                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12712                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12713                 }
12714                 pic16_toBoolean(right);
12715                 pic16_aopPut(AOP(result),"a",0);
12716                 goto release ;
12717         }
12718
12719         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12720           int offset = 1;
12721
12722                 size = AOP_SIZE(result);
12723
12724                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12725
12726                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12727                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12728                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12729
12730                 while (size--)
12731                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12732
12733                 goto release;
12734         }
12735
12736         if(IS_BITFIELD(getSpec(restype))
12737           && IS_BITFIELD(getSpec(rtype))) {
12738           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12739         }
12740
12741         /* if they are the same size : or less */
12742         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12743
12744                 /* if they are in the same place */
12745                 if (pic16_sameRegs(AOP(right),AOP(result)))
12746                         goto release;
12747
12748                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12749 #if 0
12750                 if (IS_PTR_CONST(rtype))
12751 #else
12752                 if (IS_CODEPTR(rtype))
12753 #endif
12754                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12755
12756 #if 0
12757                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12758 #else
12759                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12760 #endif
12761                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12762
12763 #if 0
12764                 if(AOP_TYPE(right) == AOP_IMMD) {
12765                   pCodeOp *pcop0, *pcop1, *pcop2;
12766                   symbol *sym = OP_SYMBOL( right );
12767
12768                         size = AOP_SIZE(result);
12769                         /* low */
12770                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12771                         /* high */
12772                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12773                         /* upper */
12774                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12775         
12776                         if (size == 3) {
12777                                 pic16_emitpcode(POC_MOVLW, pcop0);
12778                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12779                                 pic16_emitpcode(POC_MOVLW, pcop1);
12780                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12781                                 pic16_emitpcode(POC_MOVLW, pcop2);
12782                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12783                         } else
12784                         if (size == 2) {
12785                                 pic16_emitpcode(POC_MOVLW, pcop0);
12786                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12787                                 pic16_emitpcode(POC_MOVLW, pcop1);
12788                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12789                         } else {
12790                                 pic16_emitpcode(POC_MOVLW, pcop0);
12791                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12792                         }
12793                 } else
12794 #endif
12795                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12796                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12797                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12798                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12799                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12800                         if(AOP_SIZE(result) <2)
12801                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12802                 } else {
12803                         /* if they in different places then copy */
12804                         size = AOP_SIZE(result);
12805                         offset = 0 ;
12806                         while (size--) {
12807                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12808                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12809                                 offset++;
12810                         }
12811                 }
12812                 goto release;
12813         }
12814
12815         /* if the result is of type pointer */
12816         if (IS_PTR(ctype)) {
12817           int p_type;
12818           sym_link *type = operandType(right);
12819           sym_link *etype = getSpec(type);
12820
12821                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12822
12823                 /* pointer to generic pointer */
12824                 if (IS_GENPTR(ctype)) {
12825                   char *l = zero;
12826             
12827                         if (IS_PTR(type)) 
12828                                 p_type = DCL_TYPE(type);
12829                         else {
12830                 /* we have to go by the storage class */
12831                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12832
12833 /*              if (SPEC_OCLS(etype)->codesp )  */
12834 /*                  p_type = CPOINTER ;  */
12835 /*              else */
12836 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12837 /*                      p_type = FPOINTER ; */
12838 /*                  else */
12839 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12840 /*                          p_type = PPOINTER; */
12841 /*                      else */
12842 /*                          if (SPEC_OCLS(etype) == idata ) */
12843 /*                              p_type = IPOINTER ; */
12844 /*                          else */
12845 /*                              p_type = POINTER ; */
12846             }
12847                 
12848             /* the first two bytes are known */
12849       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12850             size = GPTRSIZE - 1; 
12851             offset = 0 ;
12852             while (size--) {
12853               if(offset < AOP_SIZE(right)) {
12854                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12855                 pic16_mov2f(AOP(result), AOP(right), offset);
12856 /*
12857                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12858                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12859                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12860                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12861                 } else { 
12862                   
12863                   pic16_aopPut(AOP(result),
12864                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12865                          offset);
12866                 }
12867 */
12868               } else 
12869                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12870               offset++;
12871             }
12872             /* the last byte depending on type */
12873             switch (p_type) {
12874             case IPOINTER:
12875             case POINTER:
12876                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12877                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12878 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12879                 break;
12880
12881             case CPOINTER:
12882                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12883                 break;
12884
12885             case FPOINTER:
12886               pic16_emitcode(";BUG!? ","%d",__LINE__);
12887                 l = one;
12888                 break;
12889             case PPOINTER:
12890               pic16_emitcode(";BUG!? ","%d",__LINE__);
12891                 l = "#0x03";
12892                 break;
12893
12894             case GPOINTER:
12895                 if (GPTRSIZE > AOP_SIZE(right)) {
12896                   // assume data pointer... THIS MIGHT BE WRONG!
12897                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12898                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12899                 } else {
12900                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12901                 }
12902               break;
12903               
12904             default:
12905                 /* this should never happen */
12906                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
12907                        "got unknown pointer type");
12908                 exit(1);
12909             }
12910             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
12911             goto release ;
12912         }
12913         
12914         
12915         assert( 0 );
12916         /* just copy the pointers */
12917         size = AOP_SIZE(result);
12918         offset = 0 ;
12919         while (size--) {
12920             pic16_aopPut(AOP(result),
12921                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12922                    offset);
12923             offset++;
12924         }
12925         goto release ;
12926     }
12927     
12928
12929
12930     /* so we now know that the size of destination is greater
12931     than the size of the source.
12932     Now, if the next iCode is an operator then we might be
12933     able to optimize the operation without performing a cast.
12934     */
12935     if(genMixedOperation(ic))
12936       goto release;
12937
12938     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12939     
12940     /* we move to result for the size of source */
12941     size = AOP_SIZE(right);
12942     offset = 0 ;
12943
12944     while (size--) {
12945       if(!_G.resDirect)
12946         pic16_mov2f(AOP(result), AOP(right), offset);
12947       offset++;
12948     }
12949
12950     /* now depending on the sign of the destination */
12951     size = AOP_SIZE(result) - AOP_SIZE(right);
12952     /* if unsigned or not an integral type */
12953     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
12954       while (size--)
12955         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12956     } else {
12957       /* we need to extend the sign :( */
12958
12959       if(size == 1) {
12960         /* Save one instruction of casting char to int */
12961         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
12962         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12963         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
12964       } else {
12965         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
12966
12967         if(offset)
12968           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12969         else
12970           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
12971         
12972         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
12973
12974         while (size--)
12975           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
12976       }
12977     }
12978
12979 release:
12980     pic16_freeAsmop(right,NULL,ic,TRUE);
12981     pic16_freeAsmop(result,NULL,ic,TRUE);
12982
12983 }
12984
12985 /*-----------------------------------------------------------------*/
12986 /* genDjnz - generate decrement & jump if not zero instrucion      */
12987 /*-----------------------------------------------------------------*/
12988 static int genDjnz (iCode *ic, iCode *ifx)
12989 {
12990     symbol *lbl, *lbl1;
12991     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12992
12993     if (!ifx)
12994         return 0;
12995     
12996     /* if the if condition has a false label
12997        then we cannot save */
12998     if (IC_FALSE(ifx))
12999         return 0;
13000
13001     /* if the minus is not of the form 
13002        a = a - 1 */
13003     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13004         !IS_OP_LITERAL(IC_RIGHT(ic)))
13005         return 0;
13006
13007     if (operandLitValue(IC_RIGHT(ic)) != 1)
13008         return 0;
13009
13010     /* if the size of this greater than one then no
13011        saving */
13012     if (getSize(operandType(IC_RESULT(ic))) > 1)
13013         return 0;
13014
13015     /* otherwise we can save BIG */
13016     lbl = newiTempLabel(NULL);
13017     lbl1= newiTempLabel(NULL);
13018
13019     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13020     
13021     if (IS_AOP_PREG(IC_RESULT(ic))) {
13022         pic16_emitcode("dec","%s",
13023                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13024         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13025         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13026     } else {    
13027
13028
13029       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13030       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13031
13032       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13033       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13034
13035     }
13036     
13037     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13038     ifx->generated = 1;
13039     return 1;
13040 }
13041
13042 /*-----------------------------------------------------------------*/
13043 /* genReceive - generate code for a receive iCode                  */
13044 /*-----------------------------------------------------------------*/
13045 static void genReceive (iCode *ic)
13046 {    
13047
13048   FENTRY;
13049
13050 #if 0
13051   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13052         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13053 #endif
13054 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13055
13056   if (isOperandInFarSpace(IC_RESULT(ic))
13057       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13058           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13059
13060     int size = getSize(operandType(IC_RESULT(ic)));
13061     int offset =  pic16_fReturnSizePic - size;
13062
13063       assert( 0 );
13064       while (size--) {
13065         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13066                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13067                       offset++;
13068         }
13069
13070       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13071
13072       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13073       size = AOP_SIZE(IC_RESULT(ic));
13074       offset = 0;
13075       while (size--) {
13076         pic16_emitcode ("pop","acc");
13077         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13078       }
13079   } else {
13080     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13081     _G.accInUse++;
13082     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13083     _G.accInUse--;
13084
13085     /* set pseudo stack pointer to where it should be - dw*/
13086     GpsuedoStkPtr = ic->parmBytes;
13087
13088     /* setting GpsuedoStkPtr has side effects here: */
13089     assignResultValue(IC_RESULT(ic), 0);
13090   }
13091
13092   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13093 }
13094
13095 /*-----------------------------------------------------------------*/
13096 /* genDummyRead - generate code for dummy read of volatiles        */
13097 /*-----------------------------------------------------------------*/
13098 static void
13099 genDummyRead (iCode * ic)
13100 {
13101   operand *op;
13102   int i;
13103
13104   op = IC_RIGHT(ic);
13105   if (op && IS_SYMOP(op)) {
13106     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13107       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13108       return;
13109     }
13110     pic16_aopOp (op, ic, FALSE);
13111     for (i=0; i < AOP_SIZE(op); i++) {
13112       // may need to protect this from the peepholer -- this is not nice but works...
13113       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13114       pic16_mov2w (AOP(op),i);
13115       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13116     } // for i
13117     pic16_freeAsmop (op, NULL, ic, TRUE);
13118   } else if (op) {
13119     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13120   } // if
13121 }
13122
13123 /*-----------------------------------------------------------------*/
13124 /* genpic16Code - generate code for pic16 based controllers        */
13125 /*-----------------------------------------------------------------*/
13126 /*
13127  * At this point, ralloc.c has gone through the iCode and attempted
13128  * to optimize in a way suitable for a PIC. Now we've got to generate
13129  * PIC instructions that correspond to the iCode.
13130  *
13131  * Once the instructions are generated, we'll pass through both the
13132  * peep hole optimizer and the pCode optimizer.
13133  *-----------------------------------------------------------------*/
13134
13135 void genpic16Code (iCode *lic)
13136 {
13137   iCode *ic;
13138   int cln = 0;
13139
13140     lineHead = lineCurr = NULL;
13141
13142     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13143     pic16_addpBlock(pb);
13144
13145 #if 0
13146     /* if debug information required */
13147     if (options.debug && currFunc) {
13148       if (currFunc) {
13149         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13150       }
13151     }
13152 #endif
13153
13154     for (ic = lic ; ic ; ic = ic->next ) {
13155
13156       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13157       if ( cln != ic->lineno ) {
13158         if ( options.debug ) {
13159           debugFile->writeCLine (ic);
13160         }
13161         
13162         if(!options.noCcodeInAsm) {
13163           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13164               printCLine(ic->filename, ic->lineno)));
13165         }
13166
13167         cln = ic->lineno ;
13168       }
13169         
13170       if(options.iCodeInAsm) {
13171         char *l;
13172
13173           /* insert here code to print iCode as comment */
13174           l = Safe_strdup(printILine(ic));
13175           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13176       }
13177         
13178       /* if the result is marked as
13179        * spilt and rematerializable or code for
13180        * this has already been generated then
13181        * do nothing */
13182       if (resultRemat(ic) || ic->generated ) 
13183         continue ;
13184         
13185       /* depending on the operation */
13186       switch (ic->op) {
13187         case '!' :
13188           pic16_genNot(ic);
13189           break;
13190             
13191         case '~' :
13192           pic16_genCpl(ic);
13193           break;
13194             
13195         case UNARYMINUS:
13196           genUminus (ic);
13197           break;
13198             
13199         case IPUSH:
13200           genIpush (ic);
13201           break;
13202             
13203         case IPOP:
13204           /* IPOP happens only when trying to restore a 
13205            * spilt live range, if there is an ifx statement
13206            * following this pop then the if statement might
13207            * be using some of the registers being popped which
13208            * would destroy the contents of the register so
13209            * we need to check for this condition and handle it */
13210            if (ic->next
13211              && ic->next->op == IFX
13212              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13213                genIfx (ic->next,ic);
13214           else
13215             genIpop (ic);
13216           break; 
13217             
13218         case CALL:
13219           genCall (ic);
13220           break;
13221             
13222         case PCALL:
13223           genPcall (ic);
13224           break;
13225             
13226         case FUNCTION:
13227           genFunction (ic);
13228           break;
13229             
13230         case ENDFUNCTION:
13231           genEndFunction (ic);
13232           break;
13233             
13234         case RETURN:
13235           genRet (ic);
13236           break;
13237             
13238         case LABEL:
13239           genLabel (ic);
13240           break;
13241             
13242         case GOTO:
13243           genGoto (ic);
13244           break;
13245             
13246         case '+' :
13247           pic16_genPlus (ic) ;
13248           break;
13249             
13250         case '-' :
13251           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13252             pic16_genMinus (ic);
13253           break;
13254
13255         case '*' :
13256           genMult (ic);
13257           break;
13258             
13259         case '/' :
13260           genDiv (ic) ;
13261           break;
13262             
13263         case '%' :
13264           genMod (ic);
13265           break;
13266             
13267         case '>' :
13268           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13269           break;
13270             
13271         case '<' :
13272           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13273           break;
13274             
13275         case LE_OP:
13276         case GE_OP:
13277         case NE_OP:
13278           /* note these two are xlated by algebraic equivalence
13279            * during parsing SDCC.y */
13280           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13281             "got '>=' or '<=' shouldn't have come here");
13282           break;
13283
13284         case EQ_OP:
13285           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13286           break;            
13287             
13288         case AND_OP:
13289           genAndOp (ic);
13290           break;
13291             
13292         case OR_OP:
13293           genOrOp (ic);
13294           break;
13295             
13296         case '^' :
13297           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13298           break;
13299             
13300         case '|' :
13301           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13302           break;
13303             
13304         case BITWISEAND:
13305           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13306           break;
13307             
13308         case INLINEASM:
13309           genInline (ic);
13310           break;
13311             
13312         case RRC:
13313           genRRC (ic);
13314           break;
13315             
13316         case RLC:
13317           genRLC (ic);
13318           break;
13319             
13320         case GETHBIT:
13321           genGetHbit (ic);
13322           break;
13323             
13324         case LEFT_OP:
13325           genLeftShift (ic);
13326           break;
13327             
13328         case RIGHT_OP:
13329           genRightShift (ic);
13330           break;
13331             
13332         case GET_VALUE_AT_ADDRESS:
13333           genPointerGet(ic);
13334           break;
13335             
13336         case '=' :
13337           if (POINTER_SET(ic))
13338             genPointerSet(ic);
13339           else
13340             genAssign(ic);
13341           break;
13342             
13343         case IFX:
13344           genIfx (ic,NULL);
13345           break;
13346             
13347         case ADDRESS_OF:
13348           genAddrOf (ic);
13349           break;
13350             
13351         case JUMPTABLE:
13352           genJumpTab (ic);
13353           break;
13354             
13355         case CAST:
13356           genCast (ic);
13357           break;
13358             
13359         case RECEIVE:
13360           genReceive(ic);
13361           break;
13362             
13363         case SEND:
13364           addSet(&_G.sendSet,ic);
13365           break;
13366
13367         case DUMMY_READ_VOLATILE:
13368           genDummyRead (ic);
13369           break;
13370
13371         default :
13372           ic = ic;
13373       }
13374     }
13375
13376
13377     /* now we are ready to call the
13378        peep hole optimizer */
13379     if (!options.nopeep)
13380       peepHole (&lineHead);
13381
13382     /* now do the actual printing */
13383     printLine (lineHead, codeOutFile);
13384
13385 #ifdef PCODE_DEBUG
13386     DFPRINTF((stderr,"printing pBlock\n\n"));
13387     pic16_printpBlock(stdout,pb);
13388 #endif
13389
13390     return;
13391 }
13392