]> git.gag.com Git - fw/sdcc/blob - src/pic16/gen.c
* src/SDCCsymt.c (compStructSize): allow signed bitfields for PIC ports
[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       /* using PRODL as a temporary register here */
5032       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5033       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5034       pic16_mov2w (AOP(left), size);
5035       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5036       pic16_emitpcode (POC_MOVWF, pctemp);
5037       pic16_mov2w (AOP(right), size);
5038       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5039       pic16_emitpcode (POC_SUBFW, pctemp);
5040       //pic16_popReleaseTempReg(pctemp, 1);
5041     }
5042   } // if (!sign)
5043
5044   // compare remaining bytes (treat as unsigned case from above)
5045   templbl = newiTempLabel ( NULL );
5046   offs = size;
5047   while (offs--) {
5048     //DEBUGpc ("comparing bytes at offset %d", offs);
5049     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5050     mov2w_regOrLit (AOP(right), lit, offs);
5051     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5052   } // while (offs)
5053   pic16_emitpLabel (templbl->key);
5054   goto result_in_carry;
5055
5056 result_in_carry:
5057   
5058   /****************************************************
5059    * now CARRY contains the result of the comparison: *
5060    * SUBWF sets CARRY iff                             *
5061    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5062    * (F=left, W=right)                                *
5063    ****************************************************/
5064
5065   if (performedLt) {
5066     if (result && AOP_TYPE(result) != AOP_CRY) {
5067       // value will be stored
5068       emitTOGC;
5069     } else {
5070       // value wil only be used in the following genSkipc()
5071       rIfx.condition ^= 1;
5072     }
5073   } // if
5074
5075 correct_result_in_carry:
5076
5077   // assign result to variable (if neccessary)
5078   if (result && AOP_TYPE(result) != AOP_CRY) {
5079     //DEBUGpc ("assign result");
5080     size = AOP_SIZE(result);
5081     while (size--) {
5082       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5083     } // while
5084     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5085   } // if (result)
5086
5087   // perform conditional jump
5088   if (ifx) {
5089     //DEBUGpc ("generate control flow");
5090     genSkipc (&rIfx);
5091     ifx->generated = 1;
5092   } // if
5093 }
5094
5095 #elif 1         /* } */
5096                 /* { */
5097       /* original code */
5098 static void genCmp (operand *left,operand *right,
5099                     operand *result, iCode *ifx, int sign)
5100 {
5101   int size; //, offset = 0 ;
5102   unsigned long lit = 0L,i = 0;
5103   resolvedIfx rFalseIfx;
5104   //  resolvedIfx rTrueIfx;
5105   symbol *truelbl;
5106   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5107 /*
5108   if(ifx) {
5109     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5110     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5111   }
5112 */
5113
5114   FENTRY;
5115   
5116   resolveIfx(&rFalseIfx,ifx);
5117   truelbl  = newiTempLabel(NULL);
5118   size = max(AOP_SIZE(left),AOP_SIZE(right));
5119
5120   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5121
5122 #define _swapp
5123
5124   /* if literal is on the right then swap with left */
5125   if ((AOP_TYPE(right) == AOP_LIT)) {
5126     operand *tmp = right ;
5127     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5128     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5129 #ifdef _swapp
5130
5131     lit = (lit - 1) & mask;
5132     right = left;
5133     left = tmp;
5134     rFalseIfx.condition ^= 1;
5135 #endif
5136
5137   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5138     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5139   }
5140
5141
5142   //if(IC_TRUE(ifx) == NULL)
5143   /* if left & right are bit variables */
5144   if (AOP_TYPE(left) == AOP_CRY &&
5145       AOP_TYPE(right) == AOP_CRY ) {
5146     assert (0 && "bit variables used in genCmp");
5147     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5148     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5149   } else {
5150     /* subtract right from left if at the
5151        end the carry flag is set then we know that
5152        left is greater than right */
5153
5154     symbol *lbl  = newiTempLabel(NULL);
5155
5156 #if 0
5157         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5158                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5159 #endif
5160
5161 #ifndef _swapp
5162     if(AOP_TYPE(right) == AOP_LIT) {
5163
5164       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5165
5166       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5167
5168       /* special cases */
5169
5170       if(lit == 0) {
5171
5172         if(sign != 0) 
5173           genSkipCond(&rFalseIfx,left,size-1,7);
5174         else 
5175           /* no need to compare to 0...*/
5176           /* NOTE: this is a de-generate compare that most certainly 
5177            *       creates some dead code. */
5178           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5179
5180         if(ifx) ifx->generated = 1;
5181         return;
5182
5183       }
5184       size--;
5185
5186       if(size == 0) {
5187         //i = (lit >> (size*8)) & 0xff;
5188         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5189         
5190         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5191
5192         i = ((0-lit) & 0xff);
5193         if(sign) {
5194           if( i == 0x81) { 
5195             /* lit is 0x7f, all signed chars are less than
5196              * this except for 0x7f itself */
5197             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5198             genSkipz2(&rFalseIfx,0);
5199           } else {
5200             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5201             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5202             genSkipc(&rFalseIfx);
5203           }
5204
5205         } else {
5206           if(lit == 1) {
5207             genSkipz2(&rFalseIfx,1);
5208           } else {
5209             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5210             genSkipc(&rFalseIfx);
5211           }
5212         }
5213
5214         if(ifx) ifx->generated = 1;
5215         return;
5216       }
5217
5218       /* chars are out of the way. now do ints and longs */
5219
5220
5221       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5222         
5223       /* special cases */
5224
5225       if(sign) {
5226
5227         if(lit == 0) {
5228           genSkipCond(&rFalseIfx,left,size,7);
5229           if(ifx) ifx->generated = 1;
5230           return;
5231         }
5232
5233         if(lit <0x100) {
5234           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5235
5236           //rFalseIfx.condition ^= 1;
5237           //genSkipCond(&rFalseIfx,left,size,7);
5238           //rFalseIfx.condition ^= 1;
5239
5240           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5241           if(rFalseIfx.condition)
5242             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5243           else
5244             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5245
5246           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5247           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5248           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5249
5250           while(size > 1)
5251             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5252
5253           if(rFalseIfx.condition) {
5254             emitSKPZ;
5255             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5256
5257           } else {
5258             emitSKPNZ;
5259           }
5260
5261           genSkipc(&rFalseIfx);
5262           pic16_emitpLabel(truelbl->key);
5263           if(ifx) ifx->generated = 1;
5264           return;
5265
5266         }
5267
5268         if(size == 1) {
5269
5270           if( (lit & 0xff) == 0) {
5271             /* lower byte is zero */
5272             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5273             i = ((lit >> 8) & 0xff) ^0x80;
5274             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5275             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5276             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5277             genSkipc(&rFalseIfx);
5278
5279
5280             if(ifx) ifx->generated = 1;
5281             return;
5282
5283           }
5284         } else {
5285           /* Special cases for signed longs */
5286           if( (lit & 0xffffff) == 0) {
5287             /* lower byte is zero */
5288             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5289             i = ((lit >> 8*3) & 0xff) ^0x80;
5290             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5291             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5292             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5293             genSkipc(&rFalseIfx);
5294
5295
5296             if(ifx) ifx->generated = 1;
5297             return;
5298
5299           }
5300
5301         }
5302
5303
5304         if(lit & (0x80 << (size*8))) {
5305           /* lit is negative */
5306           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5307
5308           //genSkipCond(&rFalseIfx,left,size,7);
5309
5310           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5311
5312           if(rFalseIfx.condition)
5313             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5314           else
5315             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5316
5317
5318         } else {
5319           /* lit is positive */
5320           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5321           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5322           if(rFalseIfx.condition)
5323             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5324           else
5325             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5326
5327         }
5328
5329         /*
5330           This works, but is only good for ints.
5331           It also requires a "known zero" register.
5332           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5333           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5334           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5335           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5336           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5337           genSkipc(&rFalseIfx);
5338
5339           pic16_emitpLabel(truelbl->key);
5340           if(ifx) ifx->generated = 1;
5341           return;
5342         **/
5343           
5344         /* There are no more special cases, so perform a general compare */
5345   
5346         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5347         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5348
5349         while(size--) {
5350
5351           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5352           emitSKPNZ;
5353           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5354         }
5355         //rFalseIfx.condition ^= 1;
5356         genSkipc(&rFalseIfx);
5357
5358         pic16_emitpLabel(truelbl->key);
5359
5360         if(ifx) ifx->generated = 1;
5361         return;
5362
5363
5364       }
5365
5366
5367       /* sign is out of the way. So now do an unsigned compare */
5368       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5369
5370
5371       /* General case - compare to an unsigned literal on the right.*/
5372
5373       i = (lit >> (size*8)) & 0xff;
5374       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5375       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5376       while(size--) {
5377         i = (lit >> (size*8)) & 0xff;
5378
5379         if(i) {
5380           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5381           emitSKPNZ;
5382           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5383         } else {
5384           /* this byte of the lit is zero, 
5385            *if it's not the last then OR in the variable */
5386           if(size)
5387             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5388         }
5389       }
5390
5391
5392       pic16_emitpLabel(lbl->key);
5393 //      pic16_emitpLabel(truelbl->key);
5394       //if(emitFinalCheck)
5395       genSkipc(&rFalseIfx);
5396       if(sign)
5397         pic16_emitpLabel(truelbl->key);
5398
5399       if(ifx) ifx->generated = 1;
5400       return;
5401
5402
5403     }
5404 #endif  // _swapp
5405
5406     if(AOP_TYPE(left) == AOP_LIT) {
5407       //symbol *lbl = newiTempLabel(NULL);
5408
5409       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5410
5411
5412       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5413
5414       /* Special cases */
5415       if((lit == 0) && (sign == 0)){
5416
5417         size--;
5418         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5419         while(size) 
5420           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5421
5422         genSkipz2(&rFalseIfx,0);
5423         if(ifx) ifx->generated = 1;
5424         return;
5425       }
5426
5427       if(size==1) {
5428         /* Special cases */
5429         lit &= 0xff;
5430         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5431           /* degenerate compare can never be true */
5432           if(rFalseIfx.condition == 0)
5433             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5434
5435           if(ifx) ifx->generated = 1;
5436           return;
5437         }
5438
5439         if(sign) {
5440           /* signed comparisons to a literal byte */
5441
5442           int lp1 = (lit+1) & 0xff;
5443
5444           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5445           switch (lp1) {
5446           case 0:
5447             rFalseIfx.condition ^= 1;
5448             genSkipCond(&rFalseIfx,right,0,7);
5449             break;
5450           case 0x7f:
5451             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5452             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5453             genSkipz2(&rFalseIfx,1);
5454             break;
5455           default:
5456             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5457             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5458             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5459             rFalseIfx.condition ^= 1;
5460             genSkipc(&rFalseIfx);
5461             break;
5462           }
5463         } else {
5464           /* unsigned comparisons to a literal byte */
5465
5466           switch(lit & 0xff ) {
5467           case 0:
5468             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5469             genSkipz2(&rFalseIfx,0);
5470             break;
5471           case 0x7f:
5472             rFalseIfx.condition ^= 1;
5473             genSkipCond(&rFalseIfx,right,0,7);
5474             break;
5475
5476           default:
5477             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5478             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5479             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5480             rFalseIfx.condition ^= 1;
5481             if (AOP_TYPE(result) == AOP_CRY)
5482               genSkipc(&rFalseIfx);
5483             else {
5484               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5485               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5486             }         
5487             break;
5488           }
5489         }
5490
5491         if(ifx) ifx->generated = 1;
5492         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5493                 goto check_carry;
5494         return;
5495
5496       } else {
5497
5498         /* Size is greater than 1 */
5499
5500         if(sign) {
5501           int lp1 = lit+1;
5502
5503           size--;
5504
5505           if(lp1 == 0) {
5506             /* this means lit = 0xffffffff, or -1 */
5507
5508
5509             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5510             rFalseIfx.condition ^= 1;
5511             genSkipCond(&rFalseIfx,right,size,7);
5512             if(ifx) ifx->generated = 1;
5513
5514             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5515               goto check_carry;
5516
5517             return;
5518           }
5519
5520           if(lit == 0) {
5521             int s = size;
5522
5523             if(rFalseIfx.condition) {
5524               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5525               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5526             }
5527
5528             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5529             while(size--)
5530               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5531
5532
5533             emitSKPZ;
5534             if(rFalseIfx.condition) {
5535               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5536               pic16_emitpLabel(truelbl->key);
5537             }else {
5538               rFalseIfx.condition ^= 1;
5539               genSkipCond(&rFalseIfx,right,s,7);
5540             }
5541
5542             if(ifx) ifx->generated = 1;
5543
5544             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5545               goto check_carry;
5546
5547             return;
5548           }
5549
5550           if((size == 1) &&  (0 == (lp1&0xff))) {
5551             /* lower byte of signed word is zero */
5552             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5553             i = ((lp1 >> 8) & 0xff) ^0x80;
5554             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5555             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5556             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5557
5558             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5559               emitTOGC;
5560               if(ifx) ifx->generated = 1;
5561               goto check_carry;
5562             } else {
5563               rFalseIfx.condition ^= 1;
5564               genSkipc(&rFalseIfx);
5565               if(ifx) ifx->generated = 1;
5566             }
5567
5568             return;
5569           }
5570
5571           if(lit & (0x80 << (size*8))) {
5572             /* Lit is less than zero */
5573             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5574             //rFalseIfx.condition ^= 1;
5575             //genSkipCond(&rFalseIfx,left,size,7);
5576             //rFalseIfx.condition ^= 1;
5577             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5578             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5579
5580             if(rFalseIfx.condition)
5581               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5582             else
5583               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5584
5585
5586           } else {
5587             /* Lit is greater than or equal to zero */
5588             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5589             //rFalseIfx.condition ^= 1;
5590             //genSkipCond(&rFalseIfx,right,size,7);
5591             //rFalseIfx.condition ^= 1;
5592
5593             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5594             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5595
5596             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5597             if(rFalseIfx.condition)
5598               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5599             else
5600               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5601
5602           }
5603
5604           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5605           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5606
5607           while(size--) {
5608
5609             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5610             emitSKPNZ;
5611             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5612           }
5613           rFalseIfx.condition ^= 1;
5614           //rFalseIfx.condition = 1;
5615           genSkipc(&rFalseIfx);
5616
5617           pic16_emitpLabel(truelbl->key);
5618
5619           if(ifx) ifx->generated = 1;
5620
5621
5622           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5623             goto check_carry;
5624
5625           return;
5626           // end of if (sign)
5627         } else {
5628
5629           /* compare word or long to an unsigned literal on the right.*/
5630
5631
5632           size--;
5633           if(lit < 0xff) {
5634             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5635             switch (lit) {
5636             case 0:
5637               break; /* handled above */
5638 /*
5639             case 0xff:
5640               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5641               while(size--)
5642                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5643               genSkipz2(&rFalseIfx,0);
5644               break;
5645 */
5646             default:
5647               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5648               while(--size)
5649                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5650
5651               emitSKPZ;
5652               if(rFalseIfx.condition)
5653                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5654               else
5655                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5656
5657
5658               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5659               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5660
5661               rFalseIfx.condition ^= 1;
5662               genSkipc(&rFalseIfx);
5663             }
5664
5665             pic16_emitpLabel(truelbl->key);
5666
5667             if(ifx) ifx->generated = 1;
5668
5669             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5670               goto check_carry;
5671
5672             return;
5673           }
5674
5675
5676           lit++;
5677           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5678           i = (lit >> (size*8)) & 0xff;
5679
5680           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5681           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5682
5683           while(size--) {
5684             i = (lit >> (size*8)) & 0xff;
5685
5686             if(i) {
5687               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5688               emitSKPNZ;
5689               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5690             } else {
5691               /* this byte of the lit is zero, 
5692                * if it's not the last then OR in the variable */
5693               if(size)
5694                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5695             }
5696           }
5697
5698
5699           pic16_emitpLabel(lbl->key);
5700
5701           rFalseIfx.condition ^= 1;
5702
5703           genSkipc(&rFalseIfx);
5704         }
5705
5706         if(sign)
5707           pic16_emitpLabel(truelbl->key);
5708         if(ifx) ifx->generated = 1;
5709
5710             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5711               goto check_carry;
5712
5713         return;
5714       }
5715     }
5716     /* Compare two variables */
5717
5718     DEBUGpic16_emitcode(";sign","%d",sign);
5719
5720     size--;
5721     if(sign) {
5722       /* Sigh. thus sucks... */
5723       if(size) {
5724         pCodeOp *pctemp;
5725         
5726         pctemp = pic16_popGetTempReg(1);
5727         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5728         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5729         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5730         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5731         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5732         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5733         pic16_popReleaseTempReg(pctemp, 1);
5734       } else {
5735         /* Signed char comparison */
5736         /* Special thanks to Nikolai Golovchenko for this snippet */
5737         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5738         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5739         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5740         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5741         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5742         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5743
5744         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5745         genSkipc(&rFalseIfx);
5746           
5747         if(ifx) ifx->generated = 1;
5748
5749             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5750               goto check_carry;
5751
5752         return;
5753       }
5754
5755     } else {
5756
5757       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5758       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5759     }
5760
5761
5762     /* The rest of the bytes of a multi-byte compare */
5763     while (size) {
5764
5765       emitSKPZ;
5766       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5767       size--;
5768
5769       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5770       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5771
5772
5773     }
5774
5775     pic16_emitpLabel(lbl->key);
5776
5777     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5778     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5779         (AOP_TYPE(result) == AOP_REG)) {
5780       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5781       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5782     } else {
5783       genSkipc(&rFalseIfx);
5784     }         
5785     //genSkipc(&rFalseIfx);
5786     if(ifx) ifx->generated = 1;
5787
5788
5789             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5790               goto check_carry;
5791
5792     return;
5793
5794   }
5795
5796 check_carry:
5797   if ((AOP_TYPE(result) != AOP_CRY) 
5798         && AOP_SIZE(result)) {
5799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5800
5801     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5802
5803     pic16_outBitC(result);
5804   } else {
5805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5806     /* if the result is used in the next
5807        ifx conditional branch then generate
5808        code a little differently */
5809     if (ifx )
5810       genIfxJump (ifx,"c");
5811     else
5812       pic16_outBitC(result);
5813     /* leave the result in acc */
5814   }
5815
5816 }
5817
5818 #elif 0 /* VR version of genCmp() */    /* } else { */
5819
5820 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5821 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5822         operand *result, int offset, int invert_op)
5823 {
5824   /* add code here */
5825   
5826   /* check condition, > or < ?? */
5827   if(rIfx->condition != 0)invert_op ^= 1;
5828   
5829   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5830
5831   if(!ifx)invert_op ^= 1;
5832
5833   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5834       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5835   
5836   /* do selection */
5837   if(!invert_op)return POC_CPFSGT;
5838   else return POC_CPFSLT;
5839 }
5840
5841 static int compareAopfirstpass=1;
5842
5843 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5844             operand *oper, int offset, operand *result,
5845             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5846             symbol *tlbl)
5847 {
5848   int op;
5849   symbol *truelbl;
5850
5851   /* invert if there is a result to be loaded, in order to fit,
5852    * SETC/CLRC sequence */
5853   if(AOP_SIZE(result))invert_op ^= 1;
5854
5855 //  if(sign && !offset)invert_op ^= 1;
5856   
5857 //  if(sign)invert_op ^= 1;
5858   
5859   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5860
5861   if(AOP_SIZE(result) && compareAopfirstpass) {
5862     if(!ifx) {
5863       if(pcop2)
5864         pic16_emitpcode(POC_SETF, pcop2);
5865       else
5866         emitSETC;
5867     } else {
5868       if(pcop2)
5869         pic16_emitpcode(POC_CLRF, pcop2);
5870       else
5871         emitCLRC;
5872     }
5873   }
5874
5875   compareAopfirstpass = 0;
5876
5877       /* there is a bug when comparing operands with size > 1,
5878        * because higher bytes can be equal and test should be performed
5879        * to the next lower byte, current algorithm, considers operands
5880        * inequal in these cases! -- VR 20041107 */
5881
5882     
5883   if(pcop)
5884     pic16_emitpcode(op, pcop);
5885   else
5886     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5887
5888
5889   if((!sign || !offset) && AOP_SIZE(result)) {
5890     if(!ifx) {
5891       if(pcop2)
5892         pic16_emitpcode(POC_CLRF, pcop2);
5893         else
5894         emitCLRC;
5895     } else {
5896       if(pcop2)
5897         pic16_emitpcode(POC_SETF, pcop2);
5898       else
5899         emitSETC;
5900     }
5901     
5902     /* don't emit final branch (offset == 0) */
5903     if(offset) {
5904
5905       if(pcop2)
5906         pic16_emitpcode(POC_RRCF, pcop2);
5907
5908       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
5909     }
5910   } else {
5911     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
5912       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
5913             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
5914
5915       truelbl = newiTempLabel( NULL );
5916       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
5917       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
5918         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
5919       else
5920         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5921       pic16_emitpLabel(truelbl->key);
5922     } else {
5923       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
5924     }
5925   }
5926 }
5927
5928 static void genCmp (operand *left, operand *right,
5929                     operand *result, iCode *ifx, int sign)
5930 {
5931   int size, cmpop=1;
5932   long lit = 0L;
5933   resolvedIfx rFalseIfx;
5934   symbol *falselbl, *tlbl;
5935
5936     FENTRY;
5937     
5938     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5939
5940     resolveIfx(&rFalseIfx, ifx);
5941     size = max(AOP_SIZE(left), AOP_SIZE(right));
5942     
5943     /* if left & right are bit variables */
5944     if(AOP_TYPE(left) == AOP_CRY
5945       && AOP_TYPE(right) == AOP_CRY ) {
5946
5947         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5948         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5949         
5950         werror(W_POSSBUG2, __FILE__, __LINE__);
5951         exit(-1);
5952     }
5953     
5954     /* if literal is on the right then swap with left */
5955     if((AOP_TYPE(right) == AOP_LIT)) {
5956       operand *tmp = right ;
5957 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
5958
5959         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
5960
5961 //      lit = (lit - 1) & mask;
5962         right = left;
5963         left = tmp;
5964         rFalseIfx.condition ^= 1;               /* reverse compare */
5965     } else
5966     if ((AOP_TYPE(left) == AOP_LIT)) {
5967       /* float compares are handled by support functions */
5968       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
5969     }
5970
5971     /* actual comparing algorithm */
5972 //    size = AOP_SIZE( right );
5973
5974     falselbl = newiTempLabel( NULL );
5975     if(AOP_TYPE(left) == AOP_LIT) {
5976       /* compare to literal */
5977       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
5978       
5979       if(sign) {
5980         pCodeOp *pct, *pct2;
5981         symbol *tlbl1;
5982
5983         /* signed compare */
5984         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
5985
5986         /* using PRODL:PRODH as a temporary register here */
5987         pct = pic16_popCopyReg(&pic16_pc_prodl);
5988         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
5989         tlbl = newiTempLabel( NULL );
5990         
5991         /* first compare signs:
5992          *  a. if both are positive, compare just like unsigned
5993          *  b. if both are negative, invert cmpop, compare just like unsigned
5994          *  c. if different signs, determine the result directly */
5995
5996         size--;
5997
5998 #if 1
5999         /* { */
6000         tlbl1 = newiTempLabel( NULL );
6001 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6002
6003         if(lit > 0) {
6004
6005           /* literal is zero or positive:
6006            *  a. if carry is zero, too, continue compare,
6007            *  b. if carry is set, then continue depending on cmpop ^ condition:
6008            *    1. '<' return false (literal < variable),
6009            *    2. '>' return true (literal > variable) */
6010 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6011           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6012           
6013           
6014           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6015           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6016         } else 
6017         if(lit < 0) {
6018           
6019           /* literal is negative:
6020            *  a. if carry is set, too, continue compare,
6021            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6022            *    1. '<' return true (literal < variable),
6023            *    2. '>' return false (literal > variable) */
6024 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6025           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6026           
6027           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6028           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6029         }
6030 #if 1
6031         else {
6032           /* lit == 0 */
6033           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6034           
6035           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6036           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6037         }
6038 #endif
6039         
6040         
6041         pic16_emitpLabel( tlbl1->key );
6042 #endif  /* } */
6043
6044         compareAopfirstpass=1;
6045 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6046 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6047 //        pic16_emitpcode(POC_MOVWF, pct);
6048
6049 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6050         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6051 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6052         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6053
6054         /* generic case */        
6055           while( size-- ) {
6056 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6057 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6058 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6059 //            pic16_emitpcode(POC_MOVWF, pct);
6060
6061 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6062             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6063             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6064 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6065 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6066           }
6067         
6068         if(ifx)ifx->generated = 1;
6069
6070         if(AOP_SIZE(result)) {
6071           pic16_emitpLabel(tlbl->key);
6072           pic16_emitpLabel(falselbl->key);
6073           pic16_outBitOp( result, pct2 );
6074         } else {
6075           pic16_emitpLabel(tlbl->key);
6076         }
6077       } else {
6078
6079         /* unsigned compare */      
6080         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6081     
6082         compareAopfirstpass=1;
6083         while(size--) {
6084           
6085           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6086           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6087
6088         }
6089         if(ifx)ifx->generated = 1;
6090
6091         if(AOP_SIZE(result)) {
6092           pic16_emitpLabel(falselbl->key);
6093           pic16_outBitC( result );
6094         }
6095
6096       }
6097     } else {
6098       /* compare registers */
6099       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6100
6101
6102       if(sign) {
6103         pCodeOp *pct, *pct2;
6104         
6105         /* signed compare */
6106         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6107
6108         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6109         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6110         tlbl = newiTempLabel( NULL );
6111         
6112         compareAopfirstpass=1;
6113
6114         size--;
6115         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6116 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6117         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6118         pic16_emitpcode(POC_MOVWF, pct);
6119
6120         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6121 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6122         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6123
6124         /* WREG already holds left + 0x80 */
6125         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6126         
6127         while( size-- ) {
6128           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6129 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6130           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6131           pic16_emitpcode(POC_MOVWF, pct);
6132                 
6133           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6134 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6135           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6136
6137           /* WREG already holds left + 0x80 */
6138           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6139 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6140         }
6141         
6142         if(ifx)ifx->generated = 1;
6143
6144         if(AOP_SIZE(result)) {
6145           pic16_emitpLabel(tlbl->key);
6146           pic16_emitpLabel(falselbl->key);
6147           pic16_outBitOp( result, pct2 );
6148         } else {
6149           pic16_emitpLabel(tlbl->key);
6150         }
6151
6152       } else {
6153         /* unsigned compare */      
6154         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6155
6156         compareAopfirstpass=1;
6157         while(size--) {
6158           
6159           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6160           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6161
6162         }
6163
6164         if(ifx)ifx->generated = 1;
6165         if(AOP_SIZE(result)) {
6166
6167           pic16_emitpLabel(falselbl->key);
6168           pic16_outBitC( result );
6169         }
6170
6171       }
6172     }
6173 }
6174
6175 #endif  /* } */
6176
6177
6178
6179 /*-----------------------------------------------------------------*/
6180 /* genCmpGt :- greater than comparison                             */
6181 /*-----------------------------------------------------------------*/
6182 static void genCmpGt (iCode *ic, iCode *ifx)
6183 {
6184   operand *left, *right, *result;
6185   sym_link *letype , *retype;
6186   int sign ;
6187
6188     FENTRY;
6189     
6190     left = IC_LEFT(ic);
6191     right= IC_RIGHT(ic);
6192     result = IC_RESULT(ic);
6193
6194     letype = getSpec(operandType(left));
6195     retype =getSpec(operandType(right));
6196     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6197     /* assign the amsops */
6198     pic16_aopOp (left,ic,FALSE);
6199     pic16_aopOp (right,ic,FALSE);
6200     pic16_aopOp (result,ic,TRUE);
6201
6202     genCmp(right, left, result, ifx, sign);
6203
6204     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6205     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6206     pic16_freeAsmop(result,NULL,ic,TRUE); 
6207 }
6208
6209 /*-----------------------------------------------------------------*/
6210 /* genCmpLt - less than comparisons                                */
6211 /*-----------------------------------------------------------------*/
6212 static void genCmpLt (iCode *ic, iCode *ifx)
6213 {
6214   operand *left, *right, *result;
6215   sym_link *letype , *retype;
6216   int sign ;
6217
6218     FENTRY;
6219
6220     left = IC_LEFT(ic);
6221     right= IC_RIGHT(ic);
6222     result = IC_RESULT(ic);
6223
6224     letype = getSpec(operandType(left));
6225     retype =getSpec(operandType(right));
6226     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6227
6228     /* assign the amsops */
6229     pic16_aopOp (left,ic,FALSE);
6230     pic16_aopOp (right,ic,FALSE);
6231     pic16_aopOp (result,ic,TRUE);
6232
6233     genCmp(left, right, result, ifx, sign);
6234
6235     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6236     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6237     pic16_freeAsmop(result,NULL,ic,TRUE); 
6238 }
6239
6240 #if 0
6241 // not needed ATM
6242 // FIXME reenable literal optimisation when the pic16 port is stable
6243
6244 /*-----------------------------------------------------------------*/
6245 /* genc16bit2lit - compare a 16 bit value to a literal             */
6246 /*-----------------------------------------------------------------*/
6247 static void genc16bit2lit(operand *op, int lit, int offset)
6248 {
6249   int i;
6250
6251   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6252   if( (lit&0xff) == 0) 
6253     i=1;
6254   else
6255     i=0;
6256
6257   switch( BYTEofLONG(lit,i)) { 
6258   case 0:
6259     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6260     break;
6261   case 1:
6262     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6263     break;
6264   case 0xff:
6265     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6266     break;
6267   default:
6268     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6269     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6270   }
6271
6272   i ^= 1;
6273
6274   switch( BYTEofLONG(lit,i)) { 
6275   case 0:
6276     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6277     break;
6278   case 1:
6279     emitSKPNZ;
6280     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6281     break;
6282   case 0xff:
6283     emitSKPNZ;
6284     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6285     break;
6286   default:
6287     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6288     emitSKPNZ;
6289     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6290
6291   }
6292
6293 }
6294 #endif
6295
6296 #if 0
6297 // not needed ATM
6298 /*-----------------------------------------------------------------*/
6299 /* gencjneshort - compare and jump if not equal                    */
6300 /*-----------------------------------------------------------------*/
6301 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6302 {
6303   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6304   int offset = 0;
6305   int res_offset = 0;  /* the result may be a different size then left or right */
6306   int res_size = AOP_SIZE(result);
6307   resolvedIfx rIfx;
6308   symbol *lbl, *lbl_done;
6309
6310   unsigned long lit = 0L;
6311   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6312
6313   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6314   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6315   if(result)
6316     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6317   resolveIfx(&rIfx,ifx);
6318   lbl =  newiTempLabel(NULL);
6319   lbl_done =  newiTempLabel(NULL);
6320
6321
6322   /* if the left side is a literal or 
6323      if the right is in a pointer register and left 
6324      is not */
6325   if ((AOP_TYPE(left) == AOP_LIT) || 
6326       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6327     operand *t = right;
6328     right = left;
6329     left = t;
6330   }
6331   if(AOP_TYPE(right) == AOP_LIT)
6332     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6333
6334   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6335     preserve_result = 1;
6336
6337   if(result && !preserve_result)
6338     {
6339       int i;
6340       for(i = 0; i < AOP_SIZE(result); i++)
6341         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6342     }
6343
6344
6345   /* if the right side is a literal then anything goes */
6346   if (AOP_TYPE(right) == AOP_LIT &&
6347       AOP_TYPE(left) != AOP_DIR ) {
6348     switch(size) {
6349     case 2:
6350       genc16bit2lit(left, lit, 0);
6351       emitSKPZ;
6352       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6353       break;
6354     default:
6355       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6356       while (size--) {
6357         if(lit & 0xff) {
6358           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6359           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6360         } else {
6361           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6362         }
6363
6364         emitSKPZ;
6365         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6366         offset++;
6367         if(res_offset < res_size-1)
6368           res_offset++;
6369         lit >>= 8;
6370       }
6371       break;
6372     }
6373   }
6374
6375   /* if the right side is in a register or in direct space or
6376      if the left is a pointer register & right is not */    
6377   else if (AOP_TYPE(right) == AOP_REG ||
6378            AOP_TYPE(right) == AOP_DIR || 
6379            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6380            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6381     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6382     int lbl_key = lbl->key;
6383
6384     if(result) {
6385       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6386       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6387     }else {
6388       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6389       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6390               __FUNCTION__,__LINE__);
6391       return;
6392     }
6393    
6394 /*     switch(size) { */
6395 /*     case 2: */
6396 /*       genc16bit2lit(left, lit, 0); */
6397 /*       emitSKPNZ; */
6398 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6399 /*       break; */
6400 /*     default: */
6401     while (size--) {
6402       int emit_skip=1;
6403       if((AOP_TYPE(left) == AOP_DIR) && 
6404          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6405
6406         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6407         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6408
6409       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6410             
6411         switch (lit & 0xff) {
6412         case 0:
6413           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6414           break;
6415         case 1:
6416           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6417           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6418           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6419           emit_skip=0;
6420           break;
6421         case 0xff:
6422           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6423           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6424           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6425           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6426           emit_skip=0;
6427           break;
6428         default:
6429           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6430           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6431         }
6432         lit >>= 8;
6433
6434       } else {
6435         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6436       }
6437       if(emit_skip) {
6438         if(AOP_TYPE(result) == AOP_CRY) {
6439           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6440           if(rIfx.condition)
6441             emitSKPNZ;
6442           else
6443             emitSKPZ;
6444           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6445         } else {
6446           /* fix me. probably need to check result size too */
6447           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6448           if(rIfx.condition)
6449             emitSKPZ;
6450           else
6451             emitSKPNZ;
6452           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6453           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6454         }
6455         if(ifx)
6456           ifx->generated=1;
6457       }
6458       emit_skip++;
6459       offset++;
6460       if(res_offset < res_size-1)
6461         res_offset++;
6462     }
6463 /*       break; */
6464 /*     } */
6465   } else if(AOP_TYPE(right) == AOP_REG &&
6466             AOP_TYPE(left) != AOP_DIR){
6467
6468     while(size--) {
6469       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6470       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6471       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6472       if(rIfx.condition)
6473         emitSKPNZ;
6474       else
6475         emitSKPZ;
6476       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6477       offset++;
6478       if(res_offset < res_size-1)
6479         res_offset++;
6480     }
6481       
6482   }else{
6483     /* right is a pointer reg need both a & b */
6484     while(size--) {
6485       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6486       if(strcmp(l,"b"))
6487         pic16_emitcode("mov","b,%s",l);
6488       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6489       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6490       offset++;
6491     }
6492   }
6493
6494   if(result && preserve_result)
6495     {
6496       int i;
6497       for(i = 0; i < AOP_SIZE(result); i++)
6498         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6499     }
6500
6501   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6502
6503   if(result && preserve_result)
6504     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6505
6506   if(!rIfx.condition)
6507     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6508
6509   pic16_emitpLabel(lbl->key);
6510
6511   if(result && preserve_result)
6512     {
6513       int i;
6514       for(i = 0; i < AOP_SIZE(result); i++)
6515         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6516
6517       pic16_emitpLabel(lbl_done->key);
6518    }
6519
6520   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6521
6522   if(ifx)
6523     ifx->generated = 1;
6524 }
6525 #endif
6526
6527 #if 0
6528 /*-----------------------------------------------------------------*/
6529 /* gencjne - compare and jump if not equal                         */
6530 /*-----------------------------------------------------------------*/
6531 static void gencjne(operand *left, operand *right, iCode *ifx)
6532 {
6533     symbol *tlbl  = newiTempLabel(NULL);
6534
6535     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6536     gencjneshort(left, right, lbl);
6537
6538     pic16_emitcode("mov","a,%s",one);
6539     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6540     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6541     pic16_emitcode("clr","a");
6542     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6543
6544     pic16_emitpLabel(lbl->key);
6545     pic16_emitpLabel(tlbl->key);
6546
6547 }
6548 #endif
6549
6550
6551 /*-----------------------------------------------------------------*/
6552 /* is_LitOp - check if operand has to be treated as literal        */
6553 /*-----------------------------------------------------------------*/
6554 static bool is_LitOp(operand *op)
6555 {
6556   return ((AOP_TYPE(op) == AOP_LIT)
6557       || ( (AOP_TYPE(op) == AOP_PCODE)
6558           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6559               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6560 }
6561
6562 /*-----------------------------------------------------------------*/
6563 /* is_LitAOp - check if operand has to be treated as literal        */
6564 /*-----------------------------------------------------------------*/
6565 static bool is_LitAOp(asmop *aop)
6566 {
6567   return ((aop->type == AOP_LIT)
6568       || ( (aop->type == AOP_PCODE)
6569           && ( (aop->aopu.pcop->type == PO_LITERAL)
6570               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6571 }
6572
6573
6574
6575 /*-----------------------------------------------------------------*/
6576 /* genCmpEq - generates code for equal to                          */
6577 /*-----------------------------------------------------------------*/
6578 static void genCmpEq (iCode *ic, iCode *ifx)
6579 {
6580   operand *left, *right, *result;
6581   symbol *falselbl = newiTempLabel(NULL);
6582   symbol *donelbl = newiTempLabel(NULL);
6583
6584   int preserve_result = 0;
6585   int generate_result = 0;
6586   int i=0;
6587   unsigned long lit = -1;
6588
6589   FENTRY;
6590   
6591   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6592   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6593   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6594  
6595   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6596
6597   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6598     {
6599       werror(W_POSSBUG2, __FILE__, __LINE__);
6600       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6601       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6602       goto release;
6603     }
6604
6605   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6606     {
6607       operand *tmp = right ;
6608       right = left;
6609       left = tmp;
6610     }
6611
6612   if (AOP_TYPE(right) == AOP_LIT) {
6613     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6614   }
6615
6616   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6617     preserve_result = 1;
6618
6619   if(result && AOP_SIZE(result))
6620     generate_result = 1;
6621
6622   if(generate_result && !preserve_result)
6623     {
6624       for(i = 0; i < AOP_SIZE(result); i++)
6625         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6626     }
6627
6628   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6629   for(i=0; i < AOP_SIZE(left); i++)
6630     {
6631       if(AOP_TYPE(left) != AOP_ACC)
6632         {
6633           if(is_LitOp(left))
6634             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6635           else
6636             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6637         }
6638       if(is_LitOp(right)) {
6639         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6640           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6641         }
6642       } else
6643         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6644
6645       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6646     }
6647
6648   // result == true
6649
6650   if(generate_result && preserve_result)
6651     {
6652       for(i = 0; i < AOP_SIZE(result); i++)
6653         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6654     }
6655
6656   if(generate_result)
6657     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6658
6659   if(generate_result && preserve_result)
6660     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6661
6662   if(ifx && IC_TRUE(ifx))
6663     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6664
6665   if(ifx && IC_FALSE(ifx))
6666     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6667
6668   pic16_emitpLabel(falselbl->key);
6669
6670   // result == false
6671
6672   if(ifx && IC_FALSE(ifx))
6673     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6674
6675   if(generate_result && preserve_result)
6676     {
6677       for(i = 0; i < AOP_SIZE(result); i++)
6678         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6679     }
6680
6681   pic16_emitpLabel(donelbl->key);
6682
6683   if(ifx)
6684     ifx->generated = 1;
6685
6686 release:
6687   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6688   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6689   pic16_freeAsmop(result,NULL,ic,TRUE);
6690
6691 }
6692
6693
6694 #if 0
6695 // old version kept for reference
6696
6697 /*-----------------------------------------------------------------*/
6698 /* genCmpEq - generates code for equal to                          */
6699 /*-----------------------------------------------------------------*/
6700 static void genCmpEq (iCode *ic, iCode *ifx)
6701 {
6702     operand *left, *right, *result;
6703     unsigned long lit = 0L;
6704     int size,offset=0;
6705     symbol *falselbl  = newiTempLabel(NULL);
6706
6707
6708     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6709
6710     if(ifx)
6711       DEBUGpic16_emitcode ("; ifx is non-null","");
6712     else
6713       DEBUGpic16_emitcode ("; ifx is null","");
6714
6715     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6716     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6717     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6718
6719     size = max(AOP_SIZE(left),AOP_SIZE(right));
6720
6721     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6722
6723     /* if literal, literal on the right or 
6724     if the right is in a pointer register and left 
6725     is not */
6726     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6727         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6728       operand *tmp = right ;
6729       right = left;
6730       left = tmp;
6731     }
6732
6733
6734     if(ifx && !AOP_SIZE(result)){
6735         symbol *tlbl;
6736         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6737         /* if they are both bit variables */
6738         if (AOP_TYPE(left) == AOP_CRY &&
6739             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6740                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6741             if(AOP_TYPE(right) == AOP_LIT){
6742                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6743                 if(lit == 0L){
6744                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6745                     pic16_emitcode("cpl","c");
6746                 } else if(lit == 1L) {
6747                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6748                 } else {
6749                     pic16_emitcode("clr","c");
6750                 }
6751                 /* AOP_TYPE(right) == AOP_CRY */
6752             } else {
6753                 symbol *lbl = newiTempLabel(NULL);
6754                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6755                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6756                 pic16_emitcode("cpl","c");
6757                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6758             }
6759             /* if true label then we jump if condition
6760             supplied is true */
6761             tlbl = newiTempLabel(NULL);
6762             if ( IC_TRUE(ifx) ) {
6763                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6764                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6765             } else {
6766                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6767                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6768             }
6769             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6770
6771                 {
6772                 /* left and right are both bit variables, result is carry */
6773                         resolvedIfx rIfx;
6774               
6775                         resolveIfx(&rIfx,ifx);
6776
6777                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6778                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6779                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6780                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6781                         genSkipz2(&rIfx,0);
6782                 }
6783         } else {
6784
6785                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6786
6787                         /* They're not both bit variables. Is the right a literal? */
6788                         if(AOP_TYPE(right) == AOP_LIT) {
6789                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6790             
6791                         switch(size) {
6792
6793                                 case 1:
6794                                         switch(lit & 0xff) {
6795                                                 case 1:
6796                                                                 if ( IC_TRUE(ifx) ) {
6797                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6798                                                                         emitSKPNZ;
6799                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6800                                                                 } else {
6801                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6802                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6803                                                                 }
6804                                                                 break;
6805                                                 case 0xff:
6806                                                                 if ( IC_TRUE(ifx) ) {
6807                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6808                                                                         emitSKPNZ;
6809                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6810                                                                 } else {
6811                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6812                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6813                                                                 }
6814                                                                 break;
6815                                                 default:
6816                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6817                                                                 if(lit)
6818                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6819                                                                 genSkip(ifx,'z');
6820                                         } // switch lit
6821
6822
6823                                         /* end of size == 1 */
6824                                         break;
6825               
6826                                 case 2:
6827                                         genc16bit2lit(left,lit,offset);
6828                                         genSkip(ifx,'z');
6829                                         break;
6830                                         /* end of size == 2 */
6831
6832                                 default:
6833                                         /* size is 4 */
6834                                         if(lit==0) {
6835                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6836                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6837                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6838                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6839                                                 genSkip(ifx,'z');
6840                                         } else {
6841                                                 /* search for patterns that can be optimized */
6842
6843                                                 genc16bit2lit(left,lit,0);
6844                                                 lit >>= 16;
6845                                                 if(lit) {
6846                                                                 if(IC_TRUE(ifx))
6847                                                                 emitSKPZ; // if hi word unequal
6848                                                                 else
6849                                                                 emitSKPNZ; // if hi word equal
6850                                                                 // fail early
6851                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6852                                                         genc16bit2lit(left,lit,2);
6853                                                         genSkip(ifx,'z');
6854                                                 } else {
6855                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6856                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6857                                                         genSkip(ifx,'z');
6858                                                 }
6859                                         }
6860                                                 pic16_emitpLabel(falselbl->key);
6861                                                 break;
6862
6863                         } // switch size
6864           
6865                         ifx->generated = 1;
6866                         goto release ;
6867             
6868
6869           } else if(AOP_TYPE(right) == AOP_CRY ) {
6870             /* we know the left is not a bit, but that the right is */
6871             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6872             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6873                       pic16_popGet(AOP(right),offset));
6874             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6875
6876             /* if the two are equal, then W will be 0 and the Z bit is set
6877              * we could test Z now, or go ahead and check the high order bytes if
6878              * the variable we're comparing is larger than a byte. */
6879
6880             while(--size)
6881               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6882
6883             if ( IC_TRUE(ifx) ) {
6884               emitSKPNZ;
6885               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6886               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6887             } else {
6888               emitSKPZ;
6889               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6890               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6891             }
6892
6893           } else {
6894             /* They're both variables that are larger than bits */
6895             int s = size;
6896
6897             tlbl = newiTempLabel(NULL);
6898
6899             while(size--) {
6900               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6901               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6902
6903               if ( IC_TRUE(ifx) ) {
6904                 if(size) {
6905                   emitSKPZ;
6906                 
6907                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
6908
6909                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
6910                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
6911                 } else {
6912                   emitSKPNZ;
6913
6914                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
6915
6916
6917                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6918                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6919                 }
6920               } else {
6921                 emitSKPZ;
6922
6923                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
6924
6925                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6926                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6927               }
6928               offset++;
6929             }
6930             if(s>1 && IC_TRUE(ifx)) {
6931               pic16_emitpLabel(tlbl->key);
6932               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
6933             }
6934           }
6935         }
6936         /* mark the icode as generated */
6937         ifx->generated = 1;
6938         goto release ;
6939     }
6940
6941     /* if they are both bit variables */
6942     if (AOP_TYPE(left) == AOP_CRY &&
6943         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6944         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
6945         if(AOP_TYPE(right) == AOP_LIT){
6946             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6947             if(lit == 0L){
6948                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6949                 pic16_emitcode("cpl","c");
6950             } else if(lit == 1L) {
6951                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6952             } else {
6953                 pic16_emitcode("clr","c");
6954             }
6955             /* AOP_TYPE(right) == AOP_CRY */
6956         } else {
6957             symbol *lbl = newiTempLabel(NULL);
6958             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6959             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6960             pic16_emitcode("cpl","c");
6961             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6962         }
6963         /* c = 1 if egal */
6964         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
6965             pic16_outBitC(result);
6966             goto release ;
6967         }
6968         if (ifx) {
6969             genIfxJump (ifx,"c");
6970             goto release ;
6971         }
6972         /* if the result is used in an arithmetic operation
6973         then put the result in place */
6974         pic16_outBitC(result);
6975     } else {
6976       
6977       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
6978       gencjne(left,right,result,ifx);
6979 /*
6980       if(ifx) 
6981         gencjne(left,right,newiTempLabel(NULL));
6982       else {
6983         if(IC_TRUE(ifx)->key)
6984           gencjne(left,right,IC_TRUE(ifx)->key);
6985         else
6986           gencjne(left,right,IC_FALSE(ifx)->key);
6987         ifx->generated = 1;
6988         goto release ;
6989       }
6990       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
6991         pic16_aopPut(AOP(result),"a",0);
6992         goto release ;
6993       }
6994
6995       if (ifx) {
6996         genIfxJump (ifx,"a");
6997         goto release ;
6998       }
6999 */
7000       /* if the result is used in an arithmetic operation
7001          then put the result in place */
7002 /*
7003       if (AOP_TYPE(result) != AOP_CRY) 
7004         pic16_outAcc(result);
7005 */
7006       /* leave the result in acc */
7007     }
7008
7009 release:
7010     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7011     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7012     pic16_freeAsmop(result,NULL,ic,TRUE);
7013 }
7014 #endif
7015
7016 /*-----------------------------------------------------------------*/
7017 /* ifxForOp - returns the icode containing the ifx for operand     */
7018 /*-----------------------------------------------------------------*/
7019 static iCode *ifxForOp ( operand *op, iCode *ic )
7020 {
7021   FENTRY2;
7022
7023     /* if true symbol then needs to be assigned */
7024     if (IS_TRUE_SYMOP(op))
7025         return NULL ;
7026
7027     /* if this has register type condition and
7028     the next instruction is ifx with the same operand
7029     and live to of the operand is upto the ifx only then */
7030     if (ic->next
7031         && ic->next->op == IFX
7032         && IC_COND(ic->next)->key == op->key
7033         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7034         ) {
7035                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7036           return ic->next;
7037     }
7038
7039     /*
7040     if (ic->next &&
7041         ic->next->op == IFX &&
7042         IC_COND(ic->next)->key == op->key) {
7043       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7044       return ic->next;
7045     }
7046     */
7047
7048     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7049     if (ic->next &&
7050         ic->next->op == IFX)
7051       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7052
7053     if (ic->next &&
7054         ic->next->op == IFX &&
7055         IC_COND(ic->next)->key == op->key) {
7056       DEBUGpic16_emitcode ("; "," key is okay");
7057       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7058                            OP_SYMBOL(op)->liveTo,
7059                            ic->next->seq);
7060     }
7061
7062 #if 0
7063     /* the code below is completely untested
7064      * it just allows ulong2fs.c compile -- VR */
7065          
7066     ic = ic->next;
7067     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7068                                         __FILE__, __FUNCTION__, __LINE__);
7069         
7070     /* if this has register type condition and
7071     the next instruction is ifx with the same operand
7072     and live to of the operand is upto the ifx only then */
7073     if (ic->next &&
7074         ic->next->op == IFX &&
7075         IC_COND(ic->next)->key == op->key &&
7076         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7077         return ic->next;
7078
7079     if (ic->next &&
7080         ic->next->op == IFX &&
7081         IC_COND(ic->next)->key == op->key) {
7082       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7083       return ic->next;
7084     }
7085
7086     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7087                                         __FILE__, __FUNCTION__, __LINE__);
7088
7089 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7090 #endif
7091
7092     return NULL;
7093 }
7094 /*-----------------------------------------------------------------*/
7095 /* genAndOp - for && operation                                     */
7096 /*-----------------------------------------------------------------*/
7097 static void genAndOp (iCode *ic)
7098 {
7099   operand *left,*right, *result;
7100 /*     symbol *tlbl; */
7101
7102     FENTRY;
7103
7104     /* note here that && operations that are in an
7105     if statement are taken away by backPatchLabels
7106     only those used in arthmetic operations remain */
7107     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7108     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7109     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7110
7111     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7112
7113     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7114     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7115     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7116
7117     /* if both are bit variables */
7118 /*     if (AOP_TYPE(left) == AOP_CRY && */
7119 /*         AOP_TYPE(right) == AOP_CRY ) { */
7120 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7121 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7122 /*         pic16_outBitC(result); */
7123 /*     } else { */
7124 /*         tlbl = newiTempLabel(NULL); */
7125 /*         pic16_toBoolean(left);     */
7126 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7127 /*         pic16_toBoolean(right); */
7128 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7129 /*         pic16_outBitAcc(result); */
7130 /*     } */
7131
7132     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7133     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7134     pic16_freeAsmop(result,NULL,ic,TRUE);
7135 }
7136
7137
7138 /*-----------------------------------------------------------------*/
7139 /* genOrOp - for || operation                                      */
7140 /*-----------------------------------------------------------------*/
7141 /*
7142   tsd pic port -
7143   modified this code, but it doesn't appear to ever get called
7144 */
7145
7146 static void genOrOp (iCode *ic)
7147 {
7148   operand *left,*right, *result;
7149   symbol *tlbl;
7150
7151     FENTRY;  
7152
7153   /* note here that || operations that are in an
7154     if statement are taken away by backPatchLabels
7155     only those used in arthmetic operations remain */
7156     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7157     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7158     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7159
7160     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7161
7162     /* if both are bit variables */
7163     if (AOP_TYPE(left) == AOP_CRY &&
7164         AOP_TYPE(right) == AOP_CRY ) {
7165       pic16_emitcode("clrc","");
7166       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7167                AOP(left)->aopu.aop_dir,
7168                AOP(left)->aopu.aop_dir);
7169       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7170                AOP(right)->aopu.aop_dir,
7171                AOP(right)->aopu.aop_dir);
7172       pic16_emitcode("setc","");
7173
7174     } else {
7175         tlbl = newiTempLabel(NULL);
7176         pic16_toBoolean(left);
7177         emitSKPZ;
7178         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7179         pic16_toBoolean(right);
7180         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7181
7182         pic16_outBitAcc(result);
7183     }
7184
7185     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7186     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7187     pic16_freeAsmop(result,NULL,ic,TRUE);            
7188 }
7189
7190 /*-----------------------------------------------------------------*/
7191 /* isLiteralBit - test if lit == 2^n                               */
7192 /*-----------------------------------------------------------------*/
7193 static int isLiteralBit(unsigned long lit)
7194 {
7195     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7196     0x100L,0x200L,0x400L,0x800L,
7197     0x1000L,0x2000L,0x4000L,0x8000L,
7198     0x10000L,0x20000L,0x40000L,0x80000L,
7199     0x100000L,0x200000L,0x400000L,0x800000L,
7200     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7201     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7202     int idx;
7203     
7204     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7205     for(idx = 0; idx < 32; idx++)
7206         if(lit == pw[idx])
7207             return idx+1;
7208     return 0;
7209 }
7210
7211 /*-----------------------------------------------------------------*/
7212 /* continueIfTrue -                                                */
7213 /*-----------------------------------------------------------------*/
7214 static void continueIfTrue (iCode *ic)
7215 {
7216   FENTRY;
7217   if(IC_TRUE(ic))
7218     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7219   ic->generated = 1;
7220 }
7221
7222 /*-----------------------------------------------------------------*/
7223 /* jmpIfTrue -                                                     */
7224 /*-----------------------------------------------------------------*/
7225 static void jumpIfTrue (iCode *ic)
7226 {
7227   FENTRY;
7228   if(!IC_TRUE(ic))
7229     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7230   ic->generated = 1;
7231 }
7232
7233 /*-----------------------------------------------------------------*/
7234 /* jmpTrueOrFalse -                                                */
7235 /*-----------------------------------------------------------------*/
7236 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7237 {
7238   // ugly but optimized by peephole
7239   FENTRY;
7240   if(IC_TRUE(ic)){
7241     symbol *nlbl = newiTempLabel(NULL);
7242       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7243       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7244       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7245       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7246   } else {
7247     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7248     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7249   }
7250   ic->generated = 1;
7251 }
7252
7253 /*-----------------------------------------------------------------*/
7254 /* genAnd  - code for and                                          */
7255 /*-----------------------------------------------------------------*/
7256 static void genAnd (iCode *ic, iCode *ifx)
7257 {
7258   operand *left, *right, *result;
7259   int size, offset=0;  
7260   unsigned long lit = 0L;
7261   int bytelit = 0;
7262   resolvedIfx rIfx;
7263
7264     FENTRY;
7265     
7266   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7267   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7268   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7269
7270   resolveIfx(&rIfx,ifx);
7271
7272   /* if left is a literal & right is not then exchange them */
7273   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7274       AOP_NEEDSACC(left)) {
7275     operand *tmp = right ;
7276     right = left;
7277     left = tmp;
7278   }
7279
7280   /* if result = right then exchange them */
7281   if(pic16_sameRegs(AOP(result),AOP(right))){
7282     operand *tmp = right ;
7283     right = left;
7284     left = tmp;
7285   }
7286
7287   /* if right is bit then exchange them */
7288   if (AOP_TYPE(right) == AOP_CRY &&
7289       AOP_TYPE(left) != AOP_CRY){
7290     operand *tmp = right ;
7291     right = left;
7292     left = tmp;
7293   }
7294   if(AOP_TYPE(right) == AOP_LIT)
7295     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7296
7297   size = AOP_SIZE(result);
7298
7299   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7300
7301   // if(bit & yy)
7302   // result = bit & yy;
7303   if (AOP_TYPE(left) == AOP_CRY){
7304     // c = bit & literal;
7305     if(AOP_TYPE(right) == AOP_LIT){
7306       if(lit & 1) {
7307         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7308           // no change
7309           goto release;
7310         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7311       } else {
7312         // bit(result) = 0;
7313         if(size && (AOP_TYPE(result) == AOP_CRY)){
7314           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7315           goto release;
7316         }
7317         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7318           jumpIfTrue(ifx);
7319           goto release;
7320         }
7321         pic16_emitcode("clr","c");
7322       }
7323     } else {
7324       if (AOP_TYPE(right) == AOP_CRY){
7325         // c = bit & bit;
7326         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7327         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7328       } else {
7329         // c = bit & val;
7330         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7331         // c = lsb
7332         pic16_emitcode("rrc","a");
7333         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7334       }
7335     }
7336     // bit = c
7337     // val = c
7338     if(size)
7339       pic16_outBitC(result);
7340     // if(bit & ...)
7341     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7342       genIfxJump(ifx, "c");           
7343     goto release ;
7344   }
7345
7346   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7347   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7348   if((AOP_TYPE(right) == AOP_LIT) &&
7349      (AOP_TYPE(result) == AOP_CRY) &&
7350      (AOP_TYPE(left) != AOP_CRY)){
7351     int posbit = isLiteralBit(lit);
7352     /* left &  2^n */
7353     if(posbit){
7354       posbit--;
7355       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7356       // bit = left & 2^n
7357       if(size)
7358         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7359       // if(left &  2^n)
7360       else{
7361         if(ifx){
7362 /*
7363           if(IC_TRUE(ifx)) {
7364             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7365             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7366           } else {
7367             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7368             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7369           }
7370 */
7371         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7372         size = AOP_SIZE(left);
7373
7374         {
7375           int bp = posbit, ofs=0;
7376           
7377             while(bp > 7) {
7378               bp -= 8;
7379               ofs++;
7380             }
7381
7382           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7383                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7384
7385         }
7386 /*
7387           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7388                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7389 */
7390           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7391           
7392           ifx->generated = 1;
7393         }
7394         goto release;
7395       }
7396     } else {
7397       symbol *tlbl = newiTempLabel(NULL);
7398       int sizel = AOP_SIZE(left);
7399
7400       if(size)
7401         emitSETC;
7402
7403       while(sizel--) {
7404         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7405
7406           /* patch provided by Aaron Colwell */
7407           if((posbit = isLiteralBit(bytelit)) != 0) {
7408               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7409                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7410                                                 (posbit-1),0, PO_GPR_REGISTER));
7411
7412               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7413 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7414           } else {
7415               if (bytelit == 0xff) {
7416                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7417                    * a peephole could optimize it out -- VR */
7418                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7419               } else {
7420                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7421                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7422               }
7423
7424               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7425                             pic16_popGetLabel(tlbl->key));
7426           }
7427         
7428 #if 0
7429           /* old code, left here for reference -- VR 09/2004 */
7430           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7431           // byte ==  2^n ?
7432           if((posbit = isLiteralBit(bytelit)) != 0)
7433             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7434           else{
7435             if(bytelit != 0x0FFL)
7436               pic16_emitcode("anl","a,%s",
7437                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7438             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7439           }
7440 #endif
7441         }
7442         offset++;
7443       }
7444       // bit = left & literal
7445       if(size) {
7446         emitCLRC;
7447         pic16_emitpLabel(tlbl->key);
7448       }
7449       // if(left & literal)
7450       else {
7451         if(ifx) {
7452           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7453           ifx->generated = 1;
7454         }
7455         pic16_emitpLabel(tlbl->key);
7456         goto release;
7457       }
7458     }
7459
7460     pic16_outBitC(result);
7461     goto release ;
7462   }
7463
7464   /* if left is same as result */
7465   if(pic16_sameRegs(AOP(result),AOP(left))){
7466     int know_W = -1;
7467     for(;size--; offset++,lit>>=8) {
7468       if(AOP_TYPE(right) == AOP_LIT){
7469         switch(lit & 0xff) {
7470         case 0x00:
7471           /*  and'ing with 0 has clears the result */
7472 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7473           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7474           break;
7475         case 0xff:
7476           /* and'ing with 0xff is a nop when the result and left are the same */
7477           break;
7478
7479         default:
7480           {
7481             int p = pic16_my_powof2( (~lit) & 0xff );
7482             if(p>=0) {
7483               /* only one bit is set in the literal, so use a bcf instruction */
7484 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7485               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7486
7487             } else {
7488               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7489               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7490               if(know_W != (lit&0xff))
7491                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7492               know_W = lit &0xff;
7493               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7494             }
7495           }    
7496         }
7497       } else {
7498         if (AOP_TYPE(left) == AOP_ACC) {
7499           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7500         } else {                    
7501           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7502           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7503
7504         }
7505       }
7506     }
7507
7508   } else {
7509     // left & result in different registers
7510     if(AOP_TYPE(result) == AOP_CRY){
7511       // result = bit
7512       // if(size), result in bit
7513       // if(!size && ifx), conditional oper: if(left & right)
7514       symbol *tlbl = newiTempLabel(NULL);
7515       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7516       if(size)
7517         pic16_emitcode("setb","c");
7518       while(sizer--){
7519         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7520         pic16_emitcode("anl","a,%s",
7521                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7522         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7523         offset++;
7524       }
7525       if(size){
7526         CLRC;
7527         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7528         pic16_outBitC(result);
7529       } else if(ifx)
7530         jmpTrueOrFalse(ifx, tlbl);
7531     } else {
7532       for(;(size--);offset++) {
7533         // normal case
7534         // result = left & right
7535         if(AOP_TYPE(right) == AOP_LIT){
7536           int t = (lit >> (offset*8)) & 0x0FFL;
7537           switch(t) { 
7538           case 0x00:
7539             pic16_emitcode("clrf","%s",
7540                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7541             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7542             break;
7543           case 0xff:
7544             pic16_emitcode("movf","%s,w",
7545                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7546             pic16_emitcode("movwf","%s",
7547                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7548             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7549             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7550             break;
7551           default:
7552             pic16_emitcode("movlw","0x%x",t);
7553             pic16_emitcode("andwf","%s,w",
7554                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7555             pic16_emitcode("movwf","%s",
7556                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7557               
7558             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7559             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7560             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7561           }
7562           continue;
7563         }
7564
7565         if (AOP_TYPE(left) == AOP_ACC) {
7566           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7567           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7568         } else {
7569           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7570           pic16_emitcode("andwf","%s,w",
7571                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7572           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7573           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7574         }
7575         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7576         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7577       }
7578     }
7579   }
7580
7581   release :
7582     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7583   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7584   pic16_freeAsmop(result,NULL,ic,TRUE);     
7585 }
7586
7587 /*-----------------------------------------------------------------*/
7588 /* genOr  - code for or                                            */
7589 /*-----------------------------------------------------------------*/
7590 static void genOr (iCode *ic, iCode *ifx)
7591 {
7592     operand *left, *right, *result;
7593     int size, offset=0;
7594     unsigned long lit = 0L;
7595
7596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7597
7598     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7599     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7600     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7601
7602     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7603
7604     /* if left is a literal & right is not then exchange them */
7605     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7606         AOP_NEEDSACC(left)) {
7607         operand *tmp = right ;
7608         right = left;
7609         left = tmp;
7610     }
7611
7612     /* if result = right then exchange them */
7613     if(pic16_sameRegs(AOP(result),AOP(right))){
7614         operand *tmp = right ;
7615         right = left;
7616         left = tmp;
7617     }
7618
7619     /* if right is bit then exchange them */
7620     if (AOP_TYPE(right) == AOP_CRY &&
7621         AOP_TYPE(left) != AOP_CRY){
7622         operand *tmp = right ;
7623         right = left;
7624         left = tmp;
7625     }
7626
7627     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7628
7629     if(AOP_TYPE(right) == AOP_LIT)
7630         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7631
7632     size = AOP_SIZE(result);
7633
7634     // if(bit | yy)
7635     // xx = bit | yy;
7636     if (AOP_TYPE(left) == AOP_CRY){
7637         if(AOP_TYPE(right) == AOP_LIT){
7638             // c = bit & literal;
7639             if(lit){
7640                 // lit != 0 => result = 1
7641                 if(AOP_TYPE(result) == AOP_CRY){
7642                   if(size)
7643                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7644                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7645                   //     AOP(result)->aopu.aop_dir,
7646                   //     AOP(result)->aopu.aop_dir);
7647                     else if(ifx)
7648                         continueIfTrue(ifx);
7649                     goto release;
7650                 }
7651             } else {
7652                 // lit == 0 => result = left
7653                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7654                     goto release;
7655                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7656             }
7657         } else {
7658             if (AOP_TYPE(right) == AOP_CRY){
7659               if(pic16_sameRegs(AOP(result),AOP(left))){
7660                 // c = bit | bit;
7661                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7662                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7663                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7664
7665                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7666                          AOP(result)->aopu.aop_dir,
7667                          AOP(result)->aopu.aop_dir);
7668                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7669                          AOP(right)->aopu.aop_dir,
7670                          AOP(right)->aopu.aop_dir);
7671                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7672                          AOP(result)->aopu.aop_dir,
7673                          AOP(result)->aopu.aop_dir);
7674               } else {
7675                 if( AOP_TYPE(result) == AOP_ACC) {
7676                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7677                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7678                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7679                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7680
7681                 } else {
7682
7683                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7684                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7685                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7686                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7687
7688                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7689                                  AOP(result)->aopu.aop_dir,
7690                                  AOP(result)->aopu.aop_dir);
7691                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7692                                  AOP(right)->aopu.aop_dir,
7693                                  AOP(right)->aopu.aop_dir);
7694                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7695                                  AOP(left)->aopu.aop_dir,
7696                                  AOP(left)->aopu.aop_dir);
7697                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7698                                  AOP(result)->aopu.aop_dir,
7699                                  AOP(result)->aopu.aop_dir);
7700                 }
7701               }
7702             } else {
7703                 // c = bit | val;
7704                 symbol *tlbl = newiTempLabel(NULL);
7705                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7706
7707
7708                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7709                 if( AOP_TYPE(right) == AOP_ACC) {
7710                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7711                   emitSKPNZ;
7712                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7713                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7714                 }
7715
7716
7717
7718                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7719                     pic16_emitcode(";XXX setb","c");
7720                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7721                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7722                 pic16_toBoolean(right);
7723                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7724                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7725                     jmpTrueOrFalse(ifx, tlbl);
7726                     goto release;
7727                 } else {
7728                     CLRC;
7729                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7730                 }
7731             }
7732         }
7733         // bit = c
7734         // val = c
7735         if(size)
7736             pic16_outBitC(result);
7737         // if(bit | ...)
7738         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7739             genIfxJump(ifx, "c");           
7740         goto release ;
7741     }
7742
7743     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7744     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7745     if((AOP_TYPE(right) == AOP_LIT) &&
7746        (AOP_TYPE(result) == AOP_CRY) &&
7747        (AOP_TYPE(left) != AOP_CRY)){
7748         if(lit){
7749           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7750             // result = 1
7751             if(size)
7752                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7753             else 
7754                 continueIfTrue(ifx);
7755             goto release;
7756         } else {
7757           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7758             // lit = 0, result = boolean(left)
7759             if(size)
7760                 pic16_emitcode(";XXX setb","c");
7761             pic16_toBoolean(right);
7762             if(size){
7763                 symbol *tlbl = newiTempLabel(NULL);
7764                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7765                 CLRC;
7766                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7767             } else {
7768                 genIfxJump (ifx,"a");
7769                 goto release;
7770             }
7771         }
7772         pic16_outBitC(result);
7773         goto release ;
7774     }
7775
7776     /* if left is same as result */
7777     if(pic16_sameRegs(AOP(result),AOP(left))){
7778       int know_W = -1;
7779       for(;size--; offset++,lit>>=8) {
7780         if(AOP_TYPE(right) == AOP_LIT){
7781           if((lit & 0xff) == 0)
7782             /*  or'ing with 0 has no effect */
7783             continue;
7784           else {
7785             int p = pic16_my_powof2(lit & 0xff);
7786             if(p>=0) {
7787               /* only one bit is set in the literal, so use a bsf instruction */
7788               pic16_emitpcode(POC_BSF,
7789                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7790             } else {
7791               if(know_W != (lit & 0xff))
7792                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7793               know_W = lit & 0xff;
7794               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7795             }
7796                     
7797           }
7798         } else {
7799           if (AOP_TYPE(left) == AOP_ACC) {
7800             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7801             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7802           } else {                  
7803             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7804             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7805
7806             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7807             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7808
7809           }
7810         }
7811       }
7812     } else {
7813         // left & result in different registers
7814         if(AOP_TYPE(result) == AOP_CRY){
7815             // result = bit
7816             // if(size), result in bit
7817             // if(!size && ifx), conditional oper: if(left | right)
7818             symbol *tlbl = newiTempLabel(NULL);
7819             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7820             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7821
7822
7823             if(size)
7824                 pic16_emitcode(";XXX setb","c");
7825             while(sizer--){
7826                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7827                 pic16_emitcode(";XXX orl","a,%s",
7828                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7829                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7830                 offset++;
7831             }
7832             if(size){
7833                 CLRC;
7834                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7835                 pic16_outBitC(result);
7836             } else if(ifx)
7837                 jmpTrueOrFalse(ifx, tlbl);
7838         } else for(;(size--);offset++){
7839           // normal case
7840           // result = left & right
7841           if(AOP_TYPE(right) == AOP_LIT){
7842             int t = (lit >> (offset*8)) & 0x0FFL;
7843             switch(t) { 
7844             case 0x00:
7845               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7846               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7847
7848               pic16_emitcode("movf","%s,w",
7849                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7850               pic16_emitcode("movwf","%s",
7851                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7852               break;
7853             default:
7854               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7855               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7856               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7857
7858               pic16_emitcode("movlw","0x%x",t);
7859               pic16_emitcode("iorwf","%s,w",
7860                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7861               pic16_emitcode("movwf","%s",
7862                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7863               
7864             }
7865             continue;
7866           }
7867
7868           // faster than result <- left, anl result,right
7869           // and better if result is SFR
7870           if (AOP_TYPE(left) == AOP_ACC) {
7871             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7872             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7873           } else {
7874             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7875             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7876
7877             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7878             pic16_emitcode("iorwf","%s,w",
7879                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7880           }
7881           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7882           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7883         }
7884     }
7885
7886 release :
7887     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7888     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7889     pic16_freeAsmop(result,NULL,ic,TRUE);     
7890 }
7891
7892 /*-----------------------------------------------------------------*/
7893 /* genXor - code for xclusive or                                   */
7894 /*-----------------------------------------------------------------*/
7895 static void genXor (iCode *ic, iCode *ifx)
7896 {
7897   operand *left, *right, *result;
7898   int size, offset=0;
7899   unsigned long lit = 0L;
7900
7901   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7902
7903   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7904   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7905   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7906
7907   /* if left is a literal & right is not ||
7908      if left needs acc & right does not */
7909   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7910       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
7911     operand *tmp = right ;
7912     right = left;
7913     left = tmp;
7914   }
7915
7916   /* if result = right then exchange them */
7917   if(pic16_sameRegs(AOP(result),AOP(right))){
7918     operand *tmp = right ;
7919     right = left;
7920     left = tmp;
7921   }
7922
7923   /* if right is bit then exchange them */
7924   if (AOP_TYPE(right) == AOP_CRY &&
7925       AOP_TYPE(left) != AOP_CRY){
7926     operand *tmp = right ;
7927     right = left;
7928     left = tmp;
7929   }
7930   if(AOP_TYPE(right) == AOP_LIT)
7931     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7932
7933   size = AOP_SIZE(result);
7934
7935   // if(bit ^ yy)
7936   // xx = bit ^ yy;
7937   if (AOP_TYPE(left) == AOP_CRY){
7938     if(AOP_TYPE(right) == AOP_LIT){
7939       // c = bit & literal;
7940       if(lit>>1){
7941         // lit>>1  != 0 => result = 1
7942         if(AOP_TYPE(result) == AOP_CRY){
7943           if(size)
7944             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
7945             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
7946           else if(ifx)
7947             continueIfTrue(ifx);
7948           goto release;
7949         }
7950         pic16_emitcode("setb","c");
7951       } else{
7952         // lit == (0 or 1)
7953         if(lit == 0){
7954           // lit == 0, result = left
7955           if(size && pic16_sameRegs(AOP(result),AOP(left)))
7956             goto release;
7957           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7958         } else{
7959           // lit == 1, result = not(left)
7960           if(size && pic16_sameRegs(AOP(result),AOP(left))){
7961             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
7962             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
7963             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
7964             goto release;
7965           } else {
7966             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7967             pic16_emitcode("cpl","c");
7968           }
7969         }
7970       }
7971
7972     } else {
7973       // right != literal
7974       symbol *tlbl = newiTempLabel(NULL);
7975       if (AOP_TYPE(right) == AOP_CRY){
7976         // c = bit ^ bit;
7977         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7978       }
7979       else{
7980         int sizer = AOP_SIZE(right);
7981         // c = bit ^ val
7982         // if val>>1 != 0, result = 1
7983         pic16_emitcode("setb","c");
7984         while(sizer){
7985           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
7986           if(sizer == 1)
7987             // test the msb of the lsb
7988             pic16_emitcode("anl","a,#0xfe");
7989           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7990           sizer--;
7991         }
7992         // val = (0,1)
7993         pic16_emitcode("rrc","a");
7994       }
7995       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
7996       pic16_emitcode("cpl","c");
7997       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
7998     }
7999     // bit = c
8000     // val = c
8001     if(size)
8002       pic16_outBitC(result);
8003     // if(bit | ...)
8004     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8005       genIfxJump(ifx, "c");           
8006     goto release ;
8007   }
8008
8009   if(pic16_sameRegs(AOP(result),AOP(left))){
8010     /* if left is same as result */
8011     for(;size--; offset++) {
8012       if(AOP_TYPE(right) == AOP_LIT){
8013         int t  = (lit >> (offset*8)) & 0x0FFL;
8014         if(t == 0x00L)
8015           continue;
8016         else
8017           if (IS_AOP_PREG(left)) {
8018             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8019             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8020             pic16_aopPut(AOP(result),"a",offset);
8021           } else {
8022             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8023             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8024             pic16_emitcode("xrl","%s,%s",
8025                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8026                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8027           }
8028       } else {
8029         if (AOP_TYPE(left) == AOP_ACC)
8030           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8031         else {
8032           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8033           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8034 /*
8035           if (IS_AOP_PREG(left)) {
8036             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8037             pic16_aopPut(AOP(result),"a",offset);
8038           } else
8039             pic16_emitcode("xrl","%s,a",
8040                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8041 */
8042         }
8043       }
8044     }
8045   } else {
8046     // left & result in different registers
8047     if(AOP_TYPE(result) == AOP_CRY){
8048       // result = bit
8049       // if(size), result in bit
8050       // if(!size && ifx), conditional oper: if(left ^ right)
8051       symbol *tlbl = newiTempLabel(NULL);
8052       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8053       if(size)
8054         pic16_emitcode("setb","c");
8055       while(sizer--){
8056         if((AOP_TYPE(right) == AOP_LIT) &&
8057            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8058           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8059         } else {
8060           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8061           pic16_emitcode("xrl","a,%s",
8062                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8063         }
8064         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8065         offset++;
8066       }
8067       if(size){
8068         CLRC;
8069         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8070         pic16_outBitC(result);
8071       } else if(ifx)
8072         jmpTrueOrFalse(ifx, tlbl);
8073     } else for(;(size--);offset++){
8074       // normal case
8075       // result = left & right
8076       if(AOP_TYPE(right) == AOP_LIT){
8077         int t = (lit >> (offset*8)) & 0x0FFL;
8078         switch(t) { 
8079         case 0x00:
8080           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8081           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8082           pic16_emitcode("movf","%s,w",
8083                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8084           pic16_emitcode("movwf","%s",
8085                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8086           break;
8087         case 0xff:
8088           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8089           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8090           pic16_emitcode("comf","%s,w",
8091                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8092           pic16_emitcode("movwf","%s",
8093                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8094           break;
8095         default:
8096           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8097           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8098           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8099           pic16_emitcode("movlw","0x%x",t);
8100           pic16_emitcode("xorwf","%s,w",
8101                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8102           pic16_emitcode("movwf","%s",
8103                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8104
8105         }
8106         continue;
8107       }
8108
8109       // faster than result <- left, anl result,right
8110       // and better if result is SFR
8111       if (AOP_TYPE(left) == AOP_ACC) {
8112         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8113         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8114       } else {
8115         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8116         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8117         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8119       }
8120       if ( AOP_TYPE(result) != AOP_ACC){
8121         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8122         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8123       }
8124     }
8125   }
8126
8127   release :
8128     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8129   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8130   pic16_freeAsmop(result,NULL,ic,TRUE);     
8131 }
8132
8133 /*-----------------------------------------------------------------*/
8134 /* genInline - write the inline code out                           */
8135 /*-----------------------------------------------------------------*/
8136 static void genInline (iCode *ic)
8137 {
8138   char *buffer, *bp, *bp1;
8139     
8140         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8141
8142         _G.inLine += (!options.asmpeep);
8143
8144         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8145         strcpy(buffer,IC_INLINE(ic));
8146         
8147         while((bp1=strstr(bp, "\\n"))) {
8148           *bp1++ = '\n';
8149           *bp1++ = ' ';
8150           bp = bp1;
8151         }
8152         bp = bp1 = buffer;
8153
8154 #if 0
8155   /* This is an experimental code for #pragma inline
8156      and is temporarily disabled for 2.5.0 release */
8157         if(asmInlineMap)
8158         {
8159           symbol *sym;
8160           char *s;
8161           char *cbuf;
8162           int cblen;
8163
8164             cbuf = Safe_strdup(buffer);
8165             cblen = strlen(buffer)+1;
8166             memset(cbuf, 0, cblen);
8167
8168             bp = buffer;
8169             bp1 = cbuf;
8170             while(*bp) {
8171               if(*bp != '%')*bp1++ = *bp++;
8172               else {
8173                 int i;
8174
8175                   bp++;
8176                   i = *bp - '0';
8177                   if(i>elementsInSet(asmInlineMap))break;
8178                   
8179                   bp++;
8180                   s = indexSet(asmInlineMap, i);
8181                   DEBUGpc("searching symbol s = `%s'", s);
8182                   sym = findSym(SymbolTab, NULL, s);
8183
8184                   if(sym->reqv) {
8185                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8186                   } else {
8187                     strcat(bp1, sym->rname);
8188                   }
8189                   
8190                   while(*bp1)bp1++;
8191               }
8192               
8193               if(strlen(bp1) > cblen - 16) {
8194                 int i = strlen(cbuf);
8195                 cblen += 50;
8196                 cbuf = realloc(cbuf, cblen);
8197                 memset(cbuf+i, 0, 50);
8198                 bp1 = cbuf + i;
8199               }
8200             }
8201             
8202             free(buffer);
8203             buffer = Safe_strdup( cbuf );
8204             free(cbuf);
8205             
8206             bp = bp1 = buffer;
8207         }
8208 #endif  /* 0 */
8209
8210         /* emit each line as a code */
8211         while (*bp) {
8212                 if (*bp == '\n') {
8213                         *bp++ = '\0';
8214
8215                         if(*bp1)
8216                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8217                         bp1 = bp;
8218                 } else {
8219                         if (*bp == ':') {
8220                                 bp++;
8221                                 *bp = '\0';
8222                                 bp++;
8223
8224                                 /* print label, use this special format with NULL directive
8225                                  * to denote that the argument should not be indented with tab */
8226                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8227                                 bp1 = bp;
8228                         } if (*bp == ';') {
8229                                 /* advance to end of line (prevent splitting of comments at ':' */
8230                                 while (*bp && *bp != '\n') {
8231                                         bp++;
8232                                 } // while
8233                         } else
8234                                 bp++;
8235                 }
8236         }
8237
8238         if ((bp1 != bp) && *bp1)
8239                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8240
8241
8242     Safe_free(buffer);
8243
8244     _G.inLine -= (!options.asmpeep);
8245 }
8246
8247 /*-----------------------------------------------------------------*/
8248 /* genRRC - rotate right with carry                                */
8249 /*-----------------------------------------------------------------*/
8250 static void genRRC (iCode *ic)
8251 {
8252   operand *left , *result ;
8253   int size, offset = 0, same;
8254
8255   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8256
8257   /* rotate right with carry */
8258   left = IC_LEFT(ic);
8259   result=IC_RESULT(ic);
8260   pic16_aopOp (left,ic,FALSE);
8261   pic16_aopOp (result,ic,TRUE);
8262
8263   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8264
8265   same = pic16_sameRegs(AOP(result),AOP(left));
8266
8267   size = AOP_SIZE(result);    
8268
8269   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8270
8271   /* get the lsb and put it into the carry */
8272   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8273
8274   offset = 0 ;
8275
8276   while(size--) {
8277
8278     if(same) {
8279       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8280     } else {
8281       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8282       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8283     }
8284
8285     offset++;
8286   }
8287
8288   pic16_freeAsmop(left,NULL,ic,TRUE);
8289   pic16_freeAsmop(result,NULL,ic,TRUE);
8290 }
8291
8292 /*-----------------------------------------------------------------*/
8293 /* genRLC - generate code for rotate left with carry               */
8294 /*-----------------------------------------------------------------*/
8295 static void genRLC (iCode *ic)
8296 {    
8297   operand *left , *result ;
8298   int size, offset = 0;
8299   int same;
8300
8301   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8302   /* rotate right with carry */
8303   left = IC_LEFT(ic);
8304   result=IC_RESULT(ic);
8305   pic16_aopOp (left,ic,FALSE);
8306   pic16_aopOp (result,ic,TRUE);
8307
8308   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8309
8310   same = pic16_sameRegs(AOP(result),AOP(left));
8311
8312   /* move it to the result */
8313   size = AOP_SIZE(result);    
8314
8315   /* get the msb and put it into the carry */
8316   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8317
8318   offset = 0 ;
8319
8320   while(size--) {
8321
8322     if(same) {
8323       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8324     } else {
8325       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8326       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8327     }
8328
8329     offset++;
8330   }
8331
8332
8333   pic16_freeAsmop(left,NULL,ic,TRUE);
8334   pic16_freeAsmop(result,NULL,ic,TRUE);
8335 }
8336
8337
8338 /* gpasm can get the highest order bit with HIGH/UPPER
8339  * so the following probably is not needed -- VR */
8340  
8341 /*-----------------------------------------------------------------*/
8342 /* genGetHbit - generates code get highest order bit               */
8343 /*-----------------------------------------------------------------*/
8344 static void genGetHbit (iCode *ic)
8345 {
8346     operand *left, *result;
8347     left = IC_LEFT(ic);
8348     result=IC_RESULT(ic);
8349     pic16_aopOp (left,ic,FALSE);
8350     pic16_aopOp (result,ic,FALSE);
8351
8352     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8353     /* get the highest order byte into a */
8354     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8355     if(AOP_TYPE(result) == AOP_CRY){
8356         pic16_emitcode("rlc","a");
8357         pic16_outBitC(result);
8358     }
8359     else{
8360         pic16_emitcode("rl","a");
8361         pic16_emitcode("anl","a,#0x01");
8362         pic16_outAcc(result);
8363     }
8364
8365
8366     pic16_freeAsmop(left,NULL,ic,TRUE);
8367     pic16_freeAsmop(result,NULL,ic,TRUE);
8368 }
8369
8370 #if 0
8371 /*-----------------------------------------------------------------*/
8372 /* AccRol - rotate left accumulator by known count                 */
8373 /*-----------------------------------------------------------------*/
8374 static void AccRol (int shCount)
8375 {
8376     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8377     shCount &= 0x0007;              // shCount : 0..7
8378     switch(shCount){
8379         case 0 :
8380             break;
8381         case 1 :
8382             pic16_emitcode("rl","a");
8383             break;
8384         case 2 :
8385             pic16_emitcode("rl","a");
8386             pic16_emitcode("rl","a");
8387             break;
8388         case 3 :
8389             pic16_emitcode("swap","a");
8390             pic16_emitcode("rr","a");
8391             break;
8392         case 4 :
8393             pic16_emitcode("swap","a");
8394             break;
8395         case 5 :
8396             pic16_emitcode("swap","a");
8397             pic16_emitcode("rl","a");
8398             break;
8399         case 6 :
8400             pic16_emitcode("rr","a");
8401             pic16_emitcode("rr","a");
8402             break;
8403         case 7 :
8404             pic16_emitcode("rr","a");
8405             break;
8406     }
8407 }
8408 #endif
8409
8410 /*-----------------------------------------------------------------*/
8411 /* AccLsh - left shift accumulator by known count                  */
8412 /*-----------------------------------------------------------------*/
8413 static void AccLsh (int shCount)
8414 {
8415         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8416         switch(shCount){
8417                 case 0 :
8418                         return;
8419                         break;
8420                 case 1 :
8421                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8422                         break;
8423                 case 2 :
8424                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8425                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8426                         break;
8427                 case 3 :
8428                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8429                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8430                         break;
8431                 case 4 :
8432                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8433                         break;
8434                 case 5 :
8435                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8436                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8437                         break;
8438                 case 6 :
8439                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8440                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8441                         break;
8442                 case 7 :
8443                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8444                         break;
8445         }
8446
8447         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8448 }
8449
8450 /*-----------------------------------------------------------------*/
8451 /* AccRsh - right shift accumulator by known count                 */
8452 /*-----------------------------------------------------------------*/
8453 static void AccRsh (int shCount, int andmask)
8454 {
8455         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8456         switch(shCount){
8457                 case 0 :
8458                         return; break;
8459                 case 1 :
8460                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8461                         break;
8462                 case 2 :
8463                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8464                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8465                         break;
8466                 case 3 :
8467                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8468                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8469                         break;
8470                 case 4 :
8471                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8472                         break;
8473                 case 5 :
8474                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8475                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8476                         break;
8477                 case 6 :
8478                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8479                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8480                         break;
8481                 case 7 :
8482                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8483                         break;
8484         }
8485         
8486         if(andmask)
8487                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8488         else
8489                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8490 }
8491
8492 #if 0
8493 /*-----------------------------------------------------------------*/
8494 /* AccSRsh - signed right shift accumulator by known count                 */
8495 /*-----------------------------------------------------------------*/
8496 static void AccSRsh (int shCount)
8497 {
8498     symbol *tlbl ;
8499     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8500     if(shCount != 0){
8501         if(shCount == 1){
8502             pic16_emitcode("mov","c,acc.7");
8503             pic16_emitcode("rrc","a");
8504         } else if(shCount == 2){
8505             pic16_emitcode("mov","c,acc.7");
8506             pic16_emitcode("rrc","a");
8507             pic16_emitcode("mov","c,acc.7");
8508             pic16_emitcode("rrc","a");
8509         } else {
8510             tlbl = newiTempLabel(NULL);
8511             /* rotate right accumulator */
8512             AccRol(8 - shCount);
8513             /* and kill the higher order bits */
8514             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8515             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8516             pic16_emitcode("orl","a,#0x%02x",
8517                      (unsigned char)~SRMask[shCount]);
8518             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8519         }
8520     }
8521 }
8522 #endif
8523
8524 /*-----------------------------------------------------------------*/
8525 /* shiftR1Left2Result - shift right one byte from left to result   */
8526 /*-----------------------------------------------------------------*/
8527 static void shiftR1Left2ResultSigned (operand *left, int offl,
8528                                 operand *result, int offr,
8529                                 int shCount)
8530 {
8531   int same;
8532
8533   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8534
8535   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8536
8537   switch(shCount) {
8538   case 1:
8539     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8540     if(same) 
8541       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8542     else {
8543       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8544       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8545     }
8546
8547     break;
8548   case 2:
8549
8550     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8551     if(same) 
8552       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8553     else {
8554       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8555       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8556     }
8557     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8558     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8559
8560     break;
8561
8562   case 3:
8563     if(same)
8564       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8565     else {
8566       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8567       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8568     }
8569
8570     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8571     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8572     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8573
8574     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8575     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8576
8577     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8578     break;
8579
8580   case 4:
8581     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8582     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8583     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8584     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8585     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8586     break;
8587   case 5:
8588     if(same) {
8589       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8590     } else {
8591       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8592       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8593     }
8594     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8595     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8596     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8597     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8598     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8599     break;
8600
8601   case 6:
8602     if(same) {
8603       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8604       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8605       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8606       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8607       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8608       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8609     } else {
8610       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8611       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8612       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8613       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8614       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8615     }
8616     break;
8617
8618   case 7:
8619     if(same) {
8620       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8621       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8622       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8623       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8624     } else {
8625       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8626       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8627       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8628     }
8629
8630   default:
8631     break;
8632   }
8633 }
8634
8635 /*-----------------------------------------------------------------*/
8636 /* shiftR1Left2Result - shift right one byte from left to result   */
8637 /*-----------------------------------------------------------------*/
8638 static void shiftR1Left2Result (operand *left, int offl,
8639                                 operand *result, int offr,
8640                                 int shCount, int sign)
8641 {
8642   int same;
8643
8644   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8645
8646   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8647
8648   /* Copy the msb into the carry if signed. */
8649   if(sign) {
8650     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8651     return;
8652   }
8653
8654
8655
8656   switch(shCount) {
8657   case 1:
8658     emitCLRC;
8659     if(same) 
8660       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8661     else {
8662       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8663       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8664     }
8665     break;
8666   case 2:
8667     emitCLRC;
8668     if(same) {
8669       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8670     } else {
8671       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8672       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8673     }
8674     emitCLRC;
8675     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8676
8677     break;
8678   case 3:
8679     if(same)
8680       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8681     else {
8682       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8683       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8684     }
8685
8686     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8687     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8688     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8689     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8690     break;
8691       
8692   case 4:
8693     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8694     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8695     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8696     break;
8697
8698   case 5:
8699     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8700     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8701     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8702     //emitCLRC;
8703     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8704
8705     break;
8706   case 6:
8707
8708     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8709     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8710     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8711     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8712     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8713     break;
8714
8715   case 7:
8716
8717     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8718     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8719     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8720
8721     break;
8722
8723   default:
8724     break;
8725   }
8726 }
8727
8728 /*-----------------------------------------------------------------*/
8729 /* shiftL1Left2Result - shift left one byte from left to result    */
8730 /*-----------------------------------------------------------------*/
8731 static void shiftL1Left2Result (operand *left, int offl,
8732                                 operand *result, int offr, int shCount)
8733 {
8734   int same;
8735
8736   //    char *l;
8737   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8738
8739   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8740   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8741     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8742     //    MOVA(l);
8743     /* shift left accumulator */
8744     //AccLsh(shCount); // don't comment out just yet...
8745   //    pic16_aopPut(AOP(result),"a",offr);
8746
8747   switch(shCount) {
8748   case 1:
8749     /* Shift left 1 bit position */
8750     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8751     if(same) {
8752       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8753     } else {
8754       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8755       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8756     }
8757     break;
8758   case 2:
8759     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8760     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8761     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8762     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8763     break;
8764   case 3:
8765     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8766     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8767     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8768     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8769     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8770     break;
8771   case 4:
8772     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8773     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8774     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8775     break;
8776   case 5:
8777     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8778     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8779     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8780     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8781     break;
8782   case 6:
8783     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8784     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8785     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8786     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8787     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8788     break;
8789   case 7:
8790     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8791     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8792     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8793     break;
8794
8795   default:
8796     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8797   }
8798
8799 }
8800
8801 /*-----------------------------------------------------------------*/
8802 /* movLeft2Result - move byte from left to result                  */
8803 /*-----------------------------------------------------------------*/
8804 static void movLeft2Result (operand *left, int offl,
8805                             operand *result, int offr)
8806 {
8807   char *l;
8808   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8809   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8810     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8811
8812     if (*l == '@' && (IS_AOP_PREG(result))) {
8813       pic16_emitcode("mov","a,%s",l);
8814       pic16_aopPut(AOP(result),"a",offr);
8815     } else {
8816       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8817       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8818     }
8819   }
8820 }
8821
8822 /*-----------------------------------------------------------------*/
8823 /* shiftL2Left2Result - shift left two bytes from left to result   */
8824 /*-----------------------------------------------------------------*/
8825 static void shiftL2Left2Result (operand *left, int offl,
8826                                 operand *result, int offr, int shCount)
8827 {
8828   int same = pic16_sameRegs(AOP(result), AOP(left));
8829   int i;
8830
8831   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8832
8833   if (same && (offl != offr)) { // shift bytes
8834     if (offr > offl) {
8835        for(i=1;i>-1;i--) {
8836          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8837          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8838        }
8839     } else { // just treat as different later on
8840                 same = 0;
8841     }
8842   }
8843
8844   if(same) {
8845     switch(shCount) {
8846     case 0:
8847       break;
8848     case 1:
8849     case 2:
8850     case 3:
8851
8852       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8853       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8854       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8855
8856       while(--shCount) {
8857                 emitCLRC;
8858                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8859                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8860       }
8861
8862       break;
8863     case 4:
8864     case 5:
8865       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8866       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8867       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8868       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8869       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8870       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8871       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8872       if(shCount >=5) {
8873                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8874                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8875       }
8876       break;
8877     case 6:
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_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8881       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8882       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8883       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8884       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8885       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8886       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8887       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8888       break;
8889     case 7:
8890       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8891       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8892       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8893       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8894       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8895     }
8896
8897   } else {
8898     switch(shCount) {
8899     case 0:
8900       break;
8901     case 1:
8902     case 2:
8903     case 3:
8904       /* note, use a mov/add for the shift since the mov has a
8905          chance of getting optimized out */
8906       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8907       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8908       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
8909       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
8910       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8911
8912       while(--shCount) {
8913                 emitCLRC;
8914                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8915                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8916       }
8917       break;
8918
8919     case 4:
8920     case 5:
8921       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
8922       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
8923       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
8924       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8925       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8926       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
8927       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8928       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8929
8930
8931       if(shCount == 5) {
8932                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8933                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8934       }
8935       break;
8936     case 6:
8937       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8938       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8939       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
8940       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8941
8942       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8943       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8944       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8945       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8946       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8947       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8948       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8949       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8950       break;
8951     case 7:
8952       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8953       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8954       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8955       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8956       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8957     }
8958   }
8959
8960 }
8961 /*-----------------------------------------------------------------*/
8962 /* shiftR2Left2Result - shift right two bytes from left to result  */
8963 /*-----------------------------------------------------------------*/
8964 static void shiftR2Left2Result (operand *left, int offl,
8965                                 operand *result, int offr,
8966                                 int shCount, int sign)
8967 {
8968   int same = pic16_sameRegs(AOP(result), AOP(left));
8969   int i;
8970   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
8971
8972   if (same && (offl != offr)) { // shift right bytes
8973     if (offr < offl) {
8974        for(i=0;i<2;i++) {
8975          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8976          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8977        }
8978     } else { // just treat as different later on
8979                 same = 0;
8980     }
8981   }
8982
8983   switch(shCount) {
8984   case 0:
8985     break;
8986   case 1:
8987   case 2:
8988   case 3:
8989     if(sign)
8990       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
8991     else
8992       emitCLRC;
8993
8994     if(same) {
8995       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
8996       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
8997     } else {
8998       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
8999       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9000       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9001       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9002     }
9003
9004     while(--shCount) {
9005       if(sign)
9006                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9007       else
9008                 emitCLRC;
9009       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9010       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9011     }
9012     break;
9013   case 4:
9014   case 5:
9015     if(same) {
9016
9017       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9018       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9019       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9020
9021       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9022       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9023       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9024       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9025     } else {
9026       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9027       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9028       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9029
9030       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9031       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9032       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9033       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9034       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9035     }
9036
9037     if(shCount >=5) {
9038       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9039       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9040     }
9041
9042     if(sign) {
9043       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9044       pic16_emitpcode(POC_BTFSC, 
9045                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9046       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9047     }
9048
9049     break;
9050
9051   case 6:
9052     if(same) {
9053
9054       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9055       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9056
9057       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9058       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9059       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9060       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9061       if(sign) {
9062         pic16_emitpcode(POC_BTFSC, 
9063                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9064         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9065       }
9066       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9067       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9068       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9069       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9070     } else {
9071       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9072       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9073       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9074       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9075       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9076       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9077       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9078       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9079       if(sign) {
9080         pic16_emitpcode(POC_BTFSC, 
9081                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9082         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9083       }
9084       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9085       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9086
9087         
9088     }
9089
9090     break;
9091   case 7:
9092     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9093     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9094     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9095     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9096     if(sign) {
9097       emitSKPNC;
9098       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9099     } else 
9100       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9101   }
9102 }
9103
9104
9105 /*-----------------------------------------------------------------*/
9106 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9107 /*-----------------------------------------------------------------*/
9108 static void shiftLLeftOrResult (operand *left, int offl,
9109                                 operand *result, int offr, int shCount)
9110 {
9111     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9112
9113     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9114     /* shift left accumulator */
9115     AccLsh(shCount);
9116     /* or with result */
9117     /* back to result */
9118     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9119 }
9120
9121 /*-----------------------------------------------------------------*/
9122 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9123 /*-----------------------------------------------------------------*/
9124 static void shiftRLeftOrResult (operand *left, int offl,
9125                                 operand *result, int offr, int shCount)
9126 {
9127     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9128     
9129     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9130     /* shift right accumulator */
9131     AccRsh(shCount, 1);
9132     /* or with result */
9133     /* back to result */
9134     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9135 }
9136
9137 /*-----------------------------------------------------------------*/
9138 /* genlshOne - left shift a one byte quantity by known count       */
9139 /*-----------------------------------------------------------------*/
9140 static void genlshOne (operand *result, operand *left, int shCount)
9141 {       
9142     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9143     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9144 }
9145
9146 /*-----------------------------------------------------------------*/
9147 /* genlshTwo - left shift two bytes by known amount != 0           */
9148 /*-----------------------------------------------------------------*/
9149 static void genlshTwo (operand *result,operand *left, int shCount)
9150 {
9151     int size;
9152     
9153     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9154     size = pic16_getDataSize(result);
9155
9156     /* if shCount >= 8 */
9157     if (shCount >= 8) {
9158         shCount -= 8 ;
9159
9160         if (size > 1){
9161             if (shCount)
9162                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9163             else 
9164                 movLeft2Result(left, LSB, result, MSB16);
9165         }
9166         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9167     }
9168
9169     /*  1 <= shCount <= 7 */
9170     else {  
9171         if(size == 1)
9172             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9173         else 
9174             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9175     }
9176 }
9177
9178 /*-----------------------------------------------------------------*/
9179 /* shiftLLong - shift left one long from left to result            */
9180 /* offr = LSB or MSB16                                             */
9181 /*-----------------------------------------------------------------*/
9182 static void shiftLLong (operand *left, operand *result, int offr )
9183 {
9184     int size = AOP_SIZE(result);
9185     int same = pic16_sameRegs(AOP(left),AOP(result));
9186         int i;
9187
9188     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9189
9190         if (same && (offr == MSB16)) { //shift one byte
9191                 for(i=size-1;i>=MSB16;i--) {
9192                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9193                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9194                 }
9195         } else {
9196                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9197         }
9198         
9199     if (size > LSB+offr ){
9200                 if (same) {
9201                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9202                 } else {
9203                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9204                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9205                 }
9206          }
9207
9208     if(size > MSB16+offr){
9209                 if (same) {
9210                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9211                 } else {
9212                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9213                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9214                 }
9215     }
9216
9217     if(size > MSB24+offr){
9218                 if (same) {
9219                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9220                 } else {
9221                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9222                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9223                 }
9224     }
9225
9226     if(size > MSB32+offr){
9227                 if (same) {
9228                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9229                 } else {
9230                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9231                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9232                 }
9233     }
9234     if(offr != LSB)
9235                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9236
9237 }
9238
9239 /*-----------------------------------------------------------------*/
9240 /* genlshFour - shift four byte by a known amount != 0             */
9241 /*-----------------------------------------------------------------*/
9242 static void genlshFour (operand *result, operand *left, int shCount)
9243 {
9244     int size;
9245
9246     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9247     size = AOP_SIZE(result);
9248
9249     /* if shifting more that 3 bytes */
9250     if (shCount >= 24 ) {
9251         shCount -= 24;
9252         if (shCount)
9253             /* lowest order of left goes to the highest
9254             order of the destination */
9255             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9256         else
9257             movLeft2Result(left, LSB, result, MSB32);
9258
9259                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9260                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9261                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9262
9263         return;
9264     }
9265
9266     /* more than two bytes */
9267     else if ( shCount >= 16 ) {
9268         /* lower order two bytes goes to higher order two bytes */
9269         shCount -= 16;
9270         /* if some more remaining */
9271         if (shCount)
9272             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9273         else {
9274             movLeft2Result(left, MSB16, result, MSB32);
9275             movLeft2Result(left, LSB, result, MSB24);
9276         }
9277                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9278                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9279         return;
9280     }    
9281
9282     /* if more than 1 byte */
9283     else if ( shCount >= 8 ) {
9284         /* lower order three bytes goes to higher order  three bytes */
9285         shCount -= 8;
9286         if(size == 2){
9287             if(shCount)
9288                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9289             else
9290                 movLeft2Result(left, LSB, result, MSB16);
9291         }
9292         else{   /* size = 4 */
9293             if(shCount == 0){
9294                 movLeft2Result(left, MSB24, result, MSB32);
9295                 movLeft2Result(left, MSB16, result, MSB24);
9296                 movLeft2Result(left, LSB, result, MSB16);
9297                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9298             }
9299             else if(shCount == 1)
9300                 shiftLLong(left, result, MSB16);
9301             else{
9302                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9303                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9304                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9305                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9306             }
9307         }
9308     }
9309
9310     /* 1 <= shCount <= 7 */
9311     else if(shCount <= 3)
9312     { 
9313         shiftLLong(left, result, LSB);
9314         while(--shCount >= 1)
9315             shiftLLong(result, result, LSB);
9316     }
9317     /* 3 <= shCount <= 7, optimize */
9318     else{
9319         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9320         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9321         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9322     }
9323 }
9324
9325 /*-----------------------------------------------------------------*/
9326 /* genLeftShiftLiteral - left shifting by known count              */
9327 /*-----------------------------------------------------------------*/
9328 void pic16_genLeftShiftLiteral (operand *left,
9329                                  operand *right,
9330                                  operand *result,
9331                                  iCode *ic)
9332 {    
9333     int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9334     int size;
9335
9336     FENTRY;
9337     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9338     pic16_freeAsmop(right,NULL,ic,TRUE);
9339
9340     pic16_aopOp(left,ic,FALSE);
9341     pic16_aopOp(result,ic,TRUE);
9342
9343     size = getSize(operandType(result));
9344
9345 #if VIEW_SIZE
9346     pic16_emitcode("; shift left ","result %d, left %d",size,
9347              AOP_SIZE(left));
9348 #endif
9349
9350     /* I suppose that the left size >= result size */
9351     if(shCount == 0){
9352         while(size--){
9353             movLeft2Result(left, size, result, size);
9354         }
9355     }
9356
9357     else if(shCount >= (size * 8))
9358         while(size--)
9359             pic16_aopPut(AOP(result),zero,size);
9360     else{
9361         switch (size) {
9362             case 1:
9363                 genlshOne (result,left,shCount);
9364                 break;
9365
9366             case 2:
9367             case 3:
9368                 genlshTwo (result,left,shCount);
9369                 break;
9370
9371             case 4:
9372                 genlshFour (result,left,shCount);
9373                 break;
9374         }
9375     }
9376     pic16_freeAsmop(left,NULL,ic,TRUE);
9377     pic16_freeAsmop(result,NULL,ic,TRUE);
9378 }
9379
9380 /*-----------------------------------------------------------------*
9381  * genMultiAsm - repeat assembly instruction for size of register.
9382  * if endian == 1, then the high byte (i.e base address + size of 
9383  * register) is used first else the low byte is used first;
9384  *-----------------------------------------------------------------*/
9385 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9386 {
9387
9388   int offset = 0;
9389
9390   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9391
9392   if(!reg)
9393     return;
9394
9395   if(!endian) {
9396     endian = 1;
9397   } else {
9398     endian = -1;
9399     offset = size-1;
9400   }
9401
9402   while(size--) {
9403     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9404     offset += endian;
9405   }
9406
9407 }
9408
9409 #if !(USE_GENERIC_SIGNED_SHIFT)
9410 /*-----------------------------------------------------------------*/
9411 /* genLeftShift - generates code for left shifting                 */
9412 /*-----------------------------------------------------------------*/
9413 static void genLeftShift (iCode *ic)
9414 {
9415   operand *left,*right, *result;
9416   int size, offset;
9417 //  char *l;
9418   symbol *tlbl , *tlbl1;
9419   pCodeOp *pctemp;
9420
9421   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9422
9423   right = IC_RIGHT(ic);
9424   left  = IC_LEFT(ic);
9425   result = IC_RESULT(ic);
9426
9427   pic16_aopOp(right,ic,FALSE);
9428
9429   /* if the shift count is known then do it 
9430      as efficiently as possible */
9431   if (AOP_TYPE(right) == AOP_LIT) {
9432     pic16_genLeftShiftLiteral (left,right,result,ic);
9433     return ;
9434   }
9435
9436   /* shift count is unknown then we have to form
9437    * a loop. Get the loop count in WREG : Note: we take
9438    * only the lower order byte since shifting
9439    * more than 32 bits make no sense anyway, ( the
9440    * largest size of an object can be only 32 bits ) */
9441   
9442   pic16_aopOp(left,ic,FALSE);
9443   pic16_aopOp(result,ic,FALSE);
9444
9445   /* now move the left to the result if they are not the
9446    * same, and if size > 1,
9447    * and if right is not same to result (!!!) -- VR */
9448   if (!pic16_sameRegs(AOP(left),AOP(result))
9449       && (AOP_SIZE(result) > 1)) {
9450
9451     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9452
9453     size = AOP_SIZE(result);
9454     offset=0;
9455     while (size--) {
9456
9457 #if 0
9458       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9459       if (*l == '@' && (IS_AOP_PREG(result))) {
9460
9461           pic16_emitcode("mov","a,%s",l);
9462           pic16_aopPut(AOP(result),"a",offset);
9463       } else
9464 #endif
9465       {
9466         /* we don't know if left is a literal or a register, take care -- VR */
9467         pic16_mov2f(AOP(result), AOP(left), offset);
9468       }
9469       offset++;
9470     }
9471   }
9472
9473   size = AOP_SIZE(result);
9474
9475   /* if it is only one byte then */
9476   if (size == 1) {
9477     if(optimized_for_speed) {
9478       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9479       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9480       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9481       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9482       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9483       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9484       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9485       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9486       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9487       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9488       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9489       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9490     } else {
9491
9492       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9493
9494       tlbl = newiTempLabel(NULL);
9495
9496 #if 1
9497       /* this is already done, why change it? */
9498       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9499                 pic16_mov2f(AOP(result), AOP(left), 0);
9500       }
9501 #endif
9502
9503       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9504       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9505       pic16_emitpLabel(tlbl->key);
9506       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9507       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9508       emitSKPC;
9509       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9510     }
9511     goto release ;
9512   }
9513     
9514   if (pic16_sameRegs(AOP(left),AOP(result))) {
9515
9516     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9517     
9518     tlbl = newiTempLabel(NULL);
9519     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9520     genMultiAsm(POC_RRCF, result, size,1);
9521     pic16_emitpLabel(tlbl->key);
9522     genMultiAsm(POC_RLCF, result, size,0);
9523     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9524     emitSKPC;
9525     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9526     goto release;
9527   }
9528
9529   //tlbl = newiTempLabel(NULL);
9530   //offset = 0 ;   
9531   //tlbl1 = newiTempLabel(NULL);
9532
9533   //reAdjustPreg(AOP(result));    
9534     
9535   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9536   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9537   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9538   //MOVA(l);
9539   //pic16_emitcode("add","a,acc");         
9540   //pic16_aopPut(AOP(result),"a",offset++);
9541   //while (--size) {
9542   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9543   //  MOVA(l);
9544   //  pic16_emitcode("rlc","a");         
9545   //  pic16_aopPut(AOP(result),"a",offset++);
9546   //}
9547   //reAdjustPreg(AOP(result));
9548
9549   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9550   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9551
9552
9553   tlbl = newiTempLabel(NULL);
9554   tlbl1= newiTempLabel(NULL);
9555
9556   size = AOP_SIZE(result);
9557   offset = 1;
9558
9559   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9560
9561   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9562
9563   /* offset should be 0, 1 or 3 */
9564   
9565   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9566   emitSKPNZ;
9567   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9568
9569   pic16_emitpcode(POC_MOVWF, pctemp);
9570
9571
9572   pic16_emitpLabel(tlbl->key);
9573
9574   emitCLRC;
9575   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9576   while(--size)
9577     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9578
9579   pic16_emitpcode(POC_DECFSZ,  pctemp);
9580   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9581   pic16_emitpLabel(tlbl1->key);
9582
9583   pic16_popReleaseTempReg(pctemp,1);
9584
9585
9586  release:
9587   pic16_freeAsmop (right,NULL,ic,TRUE);
9588   pic16_freeAsmop(left,NULL,ic,TRUE);
9589   pic16_freeAsmop(result,NULL,ic,TRUE);
9590 }
9591 #endif
9592
9593
9594 #if 0
9595 #error old code (left here for reference)
9596 /*-----------------------------------------------------------------*/
9597 /* genLeftShift - generates code for left shifting                 */
9598 /*-----------------------------------------------------------------*/
9599 static void genLeftShift (iCode *ic)
9600 {
9601   operand *left,*right, *result;
9602   int size, offset;
9603   char *l;
9604   symbol *tlbl , *tlbl1;
9605   pCodeOp *pctemp;
9606
9607   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9608
9609   right = IC_RIGHT(ic);
9610   left  = IC_LEFT(ic);
9611   result = IC_RESULT(ic);
9612
9613   pic16_aopOp(right,ic,FALSE);
9614
9615   /* if the shift count is known then do it 
9616      as efficiently as possible */
9617   if (AOP_TYPE(right) == AOP_LIT) {
9618     pic16_genLeftShiftLiteral (left,right,result,ic);
9619     return ;
9620   }
9621
9622   /* shift count is unknown then we have to form 
9623      a loop get the loop count in B : Note: we take
9624      only the lower order byte since shifting
9625      more that 32 bits make no sense anyway, ( the
9626      largest size of an object can be only 32 bits ) */  
9627
9628     
9629   pic16_aopOp(left,ic,FALSE);
9630   pic16_aopOp(result,ic,FALSE);
9631
9632   /* now move the left to the result if they are not the
9633      same */
9634   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9635       AOP_SIZE(result) > 1) {
9636
9637     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9638
9639     size = AOP_SIZE(result);
9640     offset=0;
9641     while (size--) {
9642       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9643       if (*l == '@' && (IS_AOP_PREG(result))) {
9644
9645         pic16_emitcode("mov","a,%s",l);
9646         pic16_aopPut(AOP(result),"a",offset);
9647       } else {
9648
9649         /* we don't know if left is a literal or a register, take care -- VR */
9650         pic16_mov2f(AOP(result), AOP(left), offset);
9651       }
9652       offset++;
9653     }
9654   }
9655
9656   size = AOP_SIZE(result);
9657
9658   /* if it is only one byte then */
9659   if (size == 1) {
9660     if(optimized_for_speed) {
9661       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9662       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9663       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9664       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9665       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9666       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9667       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9668       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9669       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9670       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9671       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9672       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9673     } else {
9674
9675       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9676
9677       tlbl = newiTempLabel(NULL);
9678       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9679                 pic16_mov2f(AOP(result), AOP(left), 0);
9680                 
9681 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9682 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9683       }
9684
9685       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9686       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9687       pic16_emitpLabel(tlbl->key);
9688       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9689       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9690       emitSKPC;
9691       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9692     }
9693     goto release ;
9694   }
9695     
9696   if (pic16_sameRegs(AOP(left),AOP(result))) {
9697
9698     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9699     
9700     tlbl = newiTempLabel(NULL);
9701     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9702     genMultiAsm(POC_RRCF, result, size,1);
9703     pic16_emitpLabel(tlbl->key);
9704     genMultiAsm(POC_RLCF, result, size,0);
9705     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9706     emitSKPC;
9707     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9708     goto release;
9709   }
9710
9711   //tlbl = newiTempLabel(NULL);
9712   //offset = 0 ;   
9713   //tlbl1 = newiTempLabel(NULL);
9714
9715   //reAdjustPreg(AOP(result));    
9716     
9717   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9718   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9719   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9720   //MOVA(l);
9721   //pic16_emitcode("add","a,acc");         
9722   //pic16_aopPut(AOP(result),"a",offset++);
9723   //while (--size) {
9724   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9725   //  MOVA(l);
9726   //  pic16_emitcode("rlc","a");         
9727   //  pic16_aopPut(AOP(result),"a",offset++);
9728   //}
9729   //reAdjustPreg(AOP(result));
9730
9731   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9732   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9733
9734
9735   tlbl = newiTempLabel(NULL);
9736   tlbl1= newiTempLabel(NULL);
9737
9738   size = AOP_SIZE(result);
9739   offset = 1;
9740
9741   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9742
9743   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9744
9745   /* offset should be 0, 1 or 3 */
9746   
9747   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9748   emitSKPNZ;
9749   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9750
9751   pic16_emitpcode(POC_MOVWF, pctemp);
9752
9753
9754   pic16_emitpLabel(tlbl->key);
9755
9756   emitCLRC;
9757   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9758   while(--size)
9759     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9760
9761   pic16_emitpcode(POC_DECFSZ,  pctemp);
9762   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9763   pic16_emitpLabel(tlbl1->key);
9764
9765   pic16_popReleaseTempReg(pctemp,1);
9766
9767
9768  release:
9769   pic16_freeAsmop (right,NULL,ic,TRUE);
9770   pic16_freeAsmop(left,NULL,ic,TRUE);
9771   pic16_freeAsmop(result,NULL,ic,TRUE);
9772 }
9773 #endif
9774
9775 /*-----------------------------------------------------------------*/
9776 /* genrshOne - right shift a one byte quantity by known count      */
9777 /*-----------------------------------------------------------------*/
9778 static void genrshOne (operand *result, operand *left,
9779                        int shCount, int sign)
9780 {
9781     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9782     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9783 }
9784
9785 /*-----------------------------------------------------------------*/
9786 /* genrshTwo - right shift two bytes by known amount != 0          */
9787 /*-----------------------------------------------------------------*/
9788 static void genrshTwo (operand *result,operand *left,
9789                        int shCount, int sign)
9790 {
9791   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9792   /* if shCount >= 8 */
9793   if (shCount >= 8) {
9794     shCount -= 8 ;
9795     if (shCount)
9796       shiftR1Left2Result(left, MSB16, result, LSB,
9797                          shCount, sign);
9798     else
9799       movLeft2Result(left, MSB16, result, LSB);
9800
9801     pic16_addSign (result, 1, sign);
9802   }
9803
9804   /*  1 <= shCount <= 7 */
9805   else
9806     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9807 }
9808
9809 /*-----------------------------------------------------------------*/
9810 /* shiftRLong - shift right one long from left to result           */
9811 /* offl = LSB or MSB16                                             */
9812 /*-----------------------------------------------------------------*/
9813 static void shiftRLong (operand *left, int offl,
9814                         operand *result, int sign)
9815 {
9816     int size = AOP_SIZE(result);
9817     int same = pic16_sameRegs(AOP(left),AOP(result));
9818     int i;
9819     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9820
9821         if (same && (offl == MSB16)) { //shift one byte right
9822                 for(i=MSB16;i<size;i++) {
9823                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9824                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9825                 }
9826         }
9827
9828     if(sign)
9829                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9830         else
9831                 emitCLRC;
9832
9833         if (same) {
9834                 if (offl == LSB)
9835                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9836         } else {
9837         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9838         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9839         }
9840
9841     if(offl == MSB16) {
9842         /* add sign of "a" */
9843         pic16_addSign(result, MSB32, sign);
9844         }
9845
9846         if (same) {
9847         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9848         } else {
9849         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9850         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9851         }
9852         
9853         if (same) {
9854         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9855         } else {
9856         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9857         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9858         }
9859
9860         if (same) {
9861         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9862         } else {
9863         if(offl == LSB){
9864                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9865                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9866         }
9867         }
9868 }
9869
9870 /*-----------------------------------------------------------------*/
9871 /* genrshFour - shift four byte by a known amount != 0             */
9872 /*-----------------------------------------------------------------*/
9873 static void genrshFour (operand *result, operand *left,
9874                         int shCount, int sign)
9875 {
9876   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9877   /* if shifting more that 3 bytes */
9878   if(shCount >= 24 ) {
9879     shCount -= 24;
9880     if(shCount)
9881       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9882     else
9883       movLeft2Result(left, MSB32, result, LSB);
9884
9885     pic16_addSign(result, MSB16, sign);
9886   }
9887   else if(shCount >= 16){
9888     shCount -= 16;
9889     if(shCount)
9890       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9891     else{
9892       movLeft2Result(left, MSB24, result, LSB);
9893       movLeft2Result(left, MSB32, result, MSB16);
9894     }
9895     pic16_addSign(result, MSB24, sign);
9896   }
9897   else if(shCount >= 8){
9898     shCount -= 8;
9899     if(shCount == 1)
9900       shiftRLong(left, MSB16, result, sign);
9901     else if(shCount == 0){
9902       movLeft2Result(left, MSB16, result, LSB);
9903       movLeft2Result(left, MSB24, result, MSB16);
9904       movLeft2Result(left, MSB32, result, MSB24);
9905       pic16_addSign(result, MSB32, sign);
9906     }
9907     else{ //shcount >= 2
9908       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
9909       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
9910       /* the last shift is signed */
9911       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
9912       pic16_addSign(result, MSB32, sign);
9913     }
9914   }
9915   else{   /* 1 <= shCount <= 7 */
9916     if(shCount <= 2){
9917       shiftRLong(left, LSB, result, sign);
9918       if(shCount == 2)
9919         shiftRLong(result, LSB, result, sign);
9920     }
9921     else{
9922       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
9923       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
9924       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
9925     }
9926   }
9927 }
9928
9929 /*-----------------------------------------------------------------*/
9930 /* genRightShiftLiteral - right shifting by known count            */
9931 /*-----------------------------------------------------------------*/
9932 static void genRightShiftLiteral (operand *left,
9933                                   operand *right,
9934                                   operand *result,
9935                                   iCode *ic,
9936                                   int sign)
9937 {    
9938   int shCount = (int) abs(floatFromVal (AOP(right)->aopu.aop_lit));
9939   int lsize,res_size;
9940
9941   pic16_freeAsmop(right,NULL,ic,TRUE);
9942
9943   pic16_aopOp(left,ic,FALSE);
9944   pic16_aopOp(result,ic,TRUE);
9945
9946   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
9947
9948 #if VIEW_SIZE
9949   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
9950                  AOP_SIZE(left));
9951 #endif
9952
9953   lsize = pic16_getDataSize(left);
9954   res_size = pic16_getDataSize(result);
9955   /* test the LEFT size !!! */
9956
9957   /* I suppose that the left size >= result size */
9958   if(shCount == 0){
9959     assert (res_size <= lsize);
9960     while (res_size--) {
9961       pic16_mov2f (AOP(result), AOP(left), res_size);
9962     } // for
9963   }
9964
9965   else if(shCount >= (lsize * 8)){
9966
9967     if(res_size == 1) {
9968       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
9969       if(sign) {
9970         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9971         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
9972       }
9973     } else {
9974
9975       if(sign) {
9976         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
9977         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
9978         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
9979         while(res_size--)
9980           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
9981
9982       } else {
9983
9984         while(res_size--)
9985           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
9986       }
9987     }
9988   } else {
9989
9990     switch (res_size) {
9991     case 1:
9992       genrshOne (result,left,shCount,sign);
9993       break;
9994
9995     case 2:
9996       genrshTwo (result,left,shCount,sign);
9997       break;
9998
9999     case 4:
10000       genrshFour (result,left,shCount,sign);
10001       break;
10002     default :
10003       break;
10004     }
10005
10006   }
10007
10008   pic16_freeAsmop(left,NULL,ic,TRUE);
10009   pic16_freeAsmop(result,NULL,ic,TRUE);
10010 }
10011
10012 #if !(USE_GENERIC_SIGNED_SHIFT)
10013 /*-----------------------------------------------------------------*/
10014 /* genSignedRightShift - right shift of signed number              */
10015 /*-----------------------------------------------------------------*/
10016 static void genSignedRightShift (iCode *ic)
10017 {
10018   operand *right, *left, *result;
10019   int size, offset;
10020   //  char *l;
10021   symbol *tlbl, *tlbl1 ;
10022   pCodeOp *pctemp;
10023
10024   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10025
10026   /* we do it the hard way put the shift count in b
10027      and loop thru preserving the sign */
10028   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10029
10030   right = IC_RIGHT(ic);
10031   left  = IC_LEFT(ic);
10032   result = IC_RESULT(ic);
10033
10034   pic16_aopOp(right,ic,FALSE);  
10035   pic16_aopOp(left,ic,FALSE);
10036   pic16_aopOp(result,ic,FALSE);
10037
10038
10039   if ( AOP_TYPE(right) == AOP_LIT) {
10040     genRightShiftLiteral (left,right,result,ic,1);
10041     return ;
10042   }
10043   /* shift count is unknown then we have to form 
10044      a loop get the loop count in B : Note: we take
10045      only the lower order byte since shifting
10046      more that 32 bits make no sense anyway, ( the
10047      largest size of an object can be only 32 bits ) */  
10048
10049   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10050   //pic16_emitcode("inc","b");
10051   //pic16_freeAsmop (right,NULL,ic,TRUE);
10052   //pic16_aopOp(left,ic,FALSE);
10053   //pic16_aopOp(result,ic,FALSE);
10054
10055   /* now move the left to the result if they are not the
10056      same */
10057   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10058       AOP_SIZE(result) > 1) {
10059
10060     size = AOP_SIZE(result);
10061     offset=0;
10062     while (size--) { 
10063       /*
10064         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10065         if (*l == '@' && IS_AOP_PREG(result)) {
10066
10067         pic16_emitcode("mov","a,%s",l);
10068         pic16_aopPut(AOP(result),"a",offset);
10069         } else
10070         pic16_aopPut(AOP(result),l,offset);
10071       */
10072       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10073       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10074
10075       offset++;
10076     }
10077   }
10078
10079   /* mov the highest order bit to OVR */    
10080   tlbl = newiTempLabel(NULL);
10081   tlbl1= newiTempLabel(NULL);
10082
10083   size = AOP_SIZE(result);
10084   offset = size - 1;
10085
10086   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10087
10088   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10089
10090   /* offset should be 0, 1 or 3 */
10091   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10092   emitSKPNZ;
10093   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10094
10095   pic16_emitpcode(POC_MOVWF, pctemp);
10096
10097
10098   pic16_emitpLabel(tlbl->key);
10099
10100   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10101   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10102
10103   while(--size) {
10104     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10105   }
10106
10107   pic16_emitpcode(POC_DECFSZ,  pctemp);
10108   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10109   pic16_emitpLabel(tlbl1->key);
10110
10111   pic16_popReleaseTempReg(pctemp,1);
10112 #if 0
10113   size = AOP_SIZE(result);
10114   offset = size - 1;
10115   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10116   pic16_emitcode("rlc","a");
10117   pic16_emitcode("mov","ov,c");
10118   /* if it is only one byte then */
10119   if (size == 1) {
10120     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10121     MOVA(l);
10122     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10123     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10124     pic16_emitcode("mov","c,ov");
10125     pic16_emitcode("rrc","a");
10126     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10127     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10128     pic16_aopPut(AOP(result),"a",0);
10129     goto release ;
10130   }
10131
10132   reAdjustPreg(AOP(result));
10133   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10134   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10135   pic16_emitcode("mov","c,ov");
10136   while (size--) {
10137     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10138     MOVA(l);
10139     pic16_emitcode("rrc","a");         
10140     pic16_aopPut(AOP(result),"a",offset--);
10141   }
10142   reAdjustPreg(AOP(result));
10143   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10144   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10145
10146  release:
10147 #endif
10148
10149   pic16_freeAsmop(left,NULL,ic,TRUE);
10150   pic16_freeAsmop(result,NULL,ic,TRUE);
10151   pic16_freeAsmop(right,NULL,ic,TRUE);
10152 }
10153 #endif
10154
10155 #if !(USE_GENERIC_SIGNED_SHIFT)
10156 #warning This implementation of genRightShift() is incomplete!
10157 /*-----------------------------------------------------------------*/
10158 /* genRightShift - generate code for right shifting                */
10159 /*-----------------------------------------------------------------*/
10160 static void genRightShift (iCode *ic)
10161 {
10162     operand *right, *left, *result;
10163     sym_link *letype ;
10164     int size, offset;
10165     char *l;
10166     symbol *tlbl, *tlbl1 ;
10167
10168     /* if signed then we do it the hard way preserve the
10169     sign bit moving it inwards */
10170     letype = getSpec(operandType(IC_LEFT(ic)));
10171     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10172
10173     if (!SPEC_USIGN(letype)) {
10174         genSignedRightShift (ic);
10175         return ;
10176     }
10177
10178     /* signed & unsigned types are treated the same : i.e. the
10179     signed is NOT propagated inwards : quoting from the
10180     ANSI - standard : "for E1 >> E2, is equivalent to division
10181     by 2**E2 if unsigned or if it has a non-negative value,
10182     otherwise the result is implementation defined ", MY definition
10183     is that the sign does not get propagated */
10184
10185     right = IC_RIGHT(ic);
10186     left  = IC_LEFT(ic);
10187     result = IC_RESULT(ic);
10188
10189     pic16_aopOp(right,ic,FALSE);
10190
10191     /* if the shift count is known then do it 
10192     as efficiently as possible */
10193     if (AOP_TYPE(right) == AOP_LIT) {
10194         genRightShiftLiteral (left,right,result,ic, 0);
10195         return ;
10196     }
10197
10198     /* shift count is unknown then we have to form 
10199     a loop get the loop count in B : Note: we take
10200     only the lower order byte since shifting
10201     more that 32 bits make no sense anyway, ( the
10202     largest size of an object can be only 32 bits ) */  
10203
10204     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10205     pic16_emitcode("inc","b");
10206     pic16_aopOp(left,ic,FALSE);
10207     pic16_aopOp(result,ic,FALSE);
10208
10209     /* now move the left to the result if they are not the
10210     same */
10211     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10212         AOP_SIZE(result) > 1) {
10213
10214         size = AOP_SIZE(result);
10215         offset=0;
10216         while (size--) {
10217             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10218             if (*l == '@' && IS_AOP_PREG(result)) {
10219
10220                 pic16_emitcode("mov","a,%s",l);
10221                 pic16_aopPut(AOP(result),"a",offset);
10222             } else
10223                 pic16_aopPut(AOP(result),l,offset);
10224             offset++;
10225         }
10226     }
10227
10228     tlbl = newiTempLabel(NULL);
10229     tlbl1= newiTempLabel(NULL);
10230     size = AOP_SIZE(result);
10231     offset = size - 1;
10232
10233     /* if it is only one byte then */
10234     if (size == 1) {
10235
10236       tlbl = newiTempLabel(NULL);
10237       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10238         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10239         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10240       }
10241
10242       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10243       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10244       pic16_emitpLabel(tlbl->key);
10245       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10246       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10247       emitSKPC;
10248       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10249
10250       goto release ;
10251     }
10252
10253     reAdjustPreg(AOP(result));
10254     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10255     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10256     CLRC;
10257     while (size--) {
10258         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10259         MOVA(l);
10260         pic16_emitcode("rrc","a");         
10261         pic16_aopPut(AOP(result),"a",offset--);
10262     }
10263     reAdjustPreg(AOP(result));
10264
10265     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10266     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10267
10268 release:
10269     pic16_freeAsmop(left,NULL,ic,TRUE);
10270     pic16_freeAsmop (right,NULL,ic,TRUE);
10271     pic16_freeAsmop(result,NULL,ic,TRUE);
10272 }
10273 #endif
10274
10275 #if (USE_GENERIC_SIGNED_SHIFT)
10276 /*-----------------------------------------------------------------*/
10277 /* genGenericShift - generates code for left or right shifting     */
10278 /*-----------------------------------------------------------------*/
10279 static void genGenericShift (iCode *ic, int isShiftLeft) {
10280   operand *left,*right, *result;
10281   int offset;
10282   int sign, signedCount;
10283   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10284   PIC_OPCODE pos_shift, neg_shift;
10285
10286   FENTRY;
10287
10288   right = IC_RIGHT(ic);
10289   left  = IC_LEFT(ic);
10290   result = IC_RESULT(ic);
10291
10292   pic16_aopOp(right,ic,FALSE);
10293   pic16_aopOp(left,ic,FALSE);
10294   pic16_aopOp(result,ic,TRUE);
10295
10296   sign = !SPEC_USIGN(operandType (left));
10297   signedCount = !SPEC_USIGN(operandType (right));
10298
10299   /* if the shift count is known then do it 
10300      as efficiently as possible */
10301   if (AOP_TYPE(right) == AOP_LIT) {
10302     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10303     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10304     // we should modify right->aopu.aop_lit here!
10305     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10306     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10307     if (isShiftLeft)
10308       pic16_genLeftShiftLiteral (left,right,result,ic);
10309     else
10310       genRightShiftLiteral (left,right,result,ic, sign);
10311
10312     goto release;
10313   } // if (right is literal)
10314
10315   /* shift count is unknown then we have to form a loop.
10316    * Note: we take only the lower order byte since shifting
10317    * more than 32 bits make no sense anyway, ( the
10318    * largest size of an object can be only 32 bits )
10319    * Note: we perform arithmetic shifts if the left operand is
10320    * signed and we do an (effective) right shift, i. e. we
10321    * shift in the sign bit from the left. */
10322    
10323   label_complete = newiTempLabel ( NULL );
10324   label_loop_pos = newiTempLabel ( NULL );
10325   label_loop_neg = NULL;
10326   label_negative = NULL;
10327   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10328   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10329
10330   if (signedCount) {
10331     // additional labels needed
10332     label_loop_neg = newiTempLabel ( NULL );
10333     label_negative = newiTempLabel ( NULL );
10334   } // if
10335
10336   // copy source to result -- this will effectively truncate the left operand to the size of result!
10337   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10338   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10339   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10340     pic16_mov2f (AOP(result),AOP(left), offset);
10341   } // for
10342
10343   // if result is longer than left, fill with zeros (or sign)
10344   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10345     if (sign && AOP_SIZE(left) > 0) {
10346       // shift signed operand -- fill with sign
10347       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10348       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10349       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10350       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10351         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10352       } // for
10353     } else {
10354       // shift unsigned operand -- fill result with zeros
10355       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10356         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10357       } // for
10358     }
10359   } // if (size mismatch)
10360
10361   pic16_mov2w (AOP(right), 0);
10362   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10363   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10364   
10365 #if 0
10366   // perform a shift by one (shift count is positive)
10367   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10368   // 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])
10369   pic16_emitpLabel (label_loop_pos->key);
10370   emitCLRC;
10371   if (sign && (pos_shift == POC_RRCF)) {
10372     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10373     emitSETC;
10374   } // if
10375   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10376   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10377   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10378 #else
10379   // perform a shift by one (shift count is positive)
10380   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10381   // 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])
10382   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10383   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10384   emitCLRC;
10385   pic16_emitpLabel (label_loop_pos->key);
10386   if (sign && (pos_shift == POC_RRCF)) {
10387     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10388     emitSETC;
10389   } // if
10390   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10391   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10392   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10393   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10394 #endif
10395
10396   if (signedCount) {
10397     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10398
10399     pic16_emitpLabel (label_negative->key);
10400     // perform a shift by -1 (shift count is negative)
10401     // 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)
10402     emitCLRC;
10403     pic16_emitpLabel (label_loop_neg->key);
10404     if (sign && (neg_shift == POC_RRCF)) {
10405       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10406       emitSETC;
10407     } // if
10408     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10409     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10410     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10411     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10412   } // if (signedCount)
10413
10414   pic16_emitpLabel (label_complete->key);
10415
10416 release:
10417   pic16_freeAsmop (right,NULL,ic,TRUE);
10418   pic16_freeAsmop(left,NULL,ic,TRUE);
10419   pic16_freeAsmop(result,NULL,ic,TRUE);
10420 }
10421
10422 static void genLeftShift (iCode *ic) {
10423   genGenericShift (ic, 1);
10424 }
10425
10426 static void genRightShift (iCode *ic) {
10427   genGenericShift (ic, 0);
10428 }
10429 #endif
10430
10431
10432 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10433 void pic16_loadFSR0(operand *op, int lit)
10434 {
10435   if(OP_SYMBOL(op)->remat || is_LitOp( op )) {
10436     pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10437   } else {
10438     assert (!OP_SYMBOL(op)->remat);
10439     // set up FSR0 with address of result
10440     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10441     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10442   }
10443 }
10444
10445 /*----------------------------------------------------------------*/
10446 /* pic16_derefPtr - move one byte from the location ptr points to */
10447 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10448 /*                  to the location ptr points to (doWrite != 0)   */
10449 /*----------------------------------------------------------------*/
10450 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10451 {
10452   switch (p_type) {
10453     case FPOINTER:
10454     case POINTER:
10455       if (!fsr0_setup || !*fsr0_setup)
10456       {
10457         pic16_loadFSR0( ptr, 0 );
10458         if (fsr0_setup) *fsr0_setup = 1;
10459       }
10460       if (doWrite)
10461         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10462       else
10463         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10464       break;
10465
10466     case GPOINTER:
10467       if (AOP(ptr)->aopu.aop_reg[2]) {
10468         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10469         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10470         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10471         pic16_emitpcode (POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(ptr),1), pic16_popCopyReg(&pic16_pc_prodl)));
10472         pic16_emitpcode (POC_MOVFW, pic16_popGet(AOP(ptr),2));
10473         pic16_callGenericPointerRW(doWrite, 1);
10474       } else {
10475         // data pointer (just 2 byte given)
10476         if (!fsr0_setup || !*fsr0_setup)
10477         {
10478           pic16_loadFSR0( ptr, 0 );
10479           if (fsr0_setup) *fsr0_setup = 1;
10480         }
10481         if (doWrite)
10482           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10483         else
10484           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10485       }
10486       break;
10487
10488     default:
10489       assert (0 && "invalid pointer type specified");
10490       break;
10491   }
10492 }
10493
10494 /*-----------------------------------------------------------------*/
10495 /* genUnpackBits - generates code for unpacking bits               */
10496 /*-----------------------------------------------------------------*/
10497 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10498 {    
10499   int shCnt ;
10500   sym_link *etype, *letype;
10501   int blen=0, bstr=0;
10502   int lbstr;
10503
10504     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10505     etype = getSpec(operandType(result));
10506     letype = getSpec(operandType(left));
10507     
10508 //    if(IS_BITFIELD(etype)) {
10509       blen = SPEC_BLEN(etype);
10510       bstr = SPEC_BSTR(etype);
10511 //    }
10512
10513     lbstr = SPEC_BSTR( letype );
10514
10515     DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10516         SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10517     
10518 #if 1
10519     if((blen == 1) && (bstr < 8)) {
10520       /* it is a single bit, so use the appropriate bit instructions */
10521       DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10522
10523       pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
10524       
10525       // distinguish (p->bitfield) and p.bitfield, remat seems to work...
10526       if(!IS_PTR(operandType(left))/* && OP_SYMBOL(left)->remat && (ptype == POINTER)*/) {
10527         /* workaround to reduce the extra lfsr instruction */
10528         pic16_emitpcode(POC_BTFSC,
10529               pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10530       } else {
10531         /* this code does only handle __data pointers correctly */
10532         assert (IS_DATA_PTR(operandType(left)));
10533         pic16_loadFSR0 (left, 0);
10534         pic16_emitpcode(POC_BTFSC,
10535               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10536       }
10537
10538       if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10539         /* unsigned bitfields result in either 0 or 1 */
10540         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
10541       } else {
10542         /* signed bitfields result in either 0 or -1 */
10543         pic16_emitpcode(POC_DECF, pic16_popCopyReg(&pic16_pc_wreg));
10544       }
10545       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10546       
10547       pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10548       return;
10549     }
10550
10551 #endif
10552
10553         /* the following call to pic16_loadFSR0 is temporary until
10554          * optimization to handle single bit assignments is added
10555          * to the function. Until then use the old safe way! -- VR */
10556
10557     if (!IS_PTR(operandType(left)) /*OP_SYMBOL(left)->remat*/) {
10558         // access symbol directly
10559         pic16_mov2w (AOP(left), 0);
10560     } else {
10561       pic16_derefPtr (left, ptype, 0, NULL);
10562     }
10563
10564         /* if we have bitdisplacement then it fits   */
10565         /* into this byte completely or if length is */
10566         /* less than a byte                          */
10567         if ((shCnt = SPEC_BSTR(etype)) || 
10568                 (SPEC_BLEN(etype) <= 8))  {
10569
10570                 /* shift right acc */
10571                 AccRsh(shCnt, 0);
10572
10573                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10574                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10575
10576 /* VR -- normally I would use the following, but since we use the hack,
10577  * to avoid the masking from AccRsh, why not mask it right now? */
10578
10579 /*
10580                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10581 */
10582
10583                 /* extend signed bitfields to 8 bits */
10584                 if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10585                 {
10586                         assert (blen + bstr > 0);
10587                         pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10588                         pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10589                 }
10590
10591                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10592
10593                 pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10594           return ;
10595         }
10596
10597
10598
10599         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
10600         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10601         exit(-1);
10602
10603     return ;
10604 }
10605
10606
10607 static void genDataPointerGet(operand *left,
10608                               operand *result,
10609                               iCode *ic)
10610 {
10611   int size, offset = 0, leoffset=0 ;
10612
10613         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10614         pic16_aopOp(result, ic, TRUE);
10615
10616         FENTRY;
10617
10618         size = AOP_SIZE(result);
10619 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10620
10621
10622 #if 0
10623         /* The following tests may save a redudant movff instruction when
10624          * accessing unions */
10625          
10626         /* if they are the same */
10627         if (operandsEqu (left, result)) {
10628                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
10629                 goto release;
10630         }
10631 #endif
10632
10633 #if 0
10634         /* if they are the same registers */
10635         if (pic16_sameRegs(AOP(left),AOP(result))) {
10636                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
10637                 goto release;
10638         }
10639 #endif
10640
10641 #if 1
10642         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10643                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10644                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10645                 goto release;
10646         }
10647 #endif
10648
10649
10650 #if 0
10651         if ( AOP_TYPE(left) == AOP_PCODE) {
10652                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
10653                                 AOP(left)->aopu.pcop->name,
10654                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
10655                                 PCOR(AOP(left)->aopu.pcop)->instance:
10656                                 PCOI(AOP(left)->aopu.pcop)->offset);
10657         }
10658 #endif
10659
10660         if(AOP(left)->aopu.pcop->type == PO_DIR)
10661                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10662
10663         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10664
10665         while (size--) {
10666                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10667                 
10668 //              pic16_DumpOp("(result)",result);
10669                 if(is_LitAOp(AOP(result))) {
10670                         pic16_mov2w(AOP(left), offset); // patch 8
10671                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10672                 } else {
10673                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10674                                 pic16_popGet(AOP(left), offset), //patch 8
10675                                 pic16_popGet(AOP(result), offset)));
10676                 }
10677
10678                 offset++;
10679                 leoffset++;
10680         }
10681
10682 release:
10683     pic16_freeAsmop(result,NULL,ic,TRUE);
10684 }
10685
10686
10687
10688 /*-----------------------------------------------------------------*/
10689 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10690 /*-----------------------------------------------------------------*/
10691 static void genNearPointerGet (operand *left, 
10692                                operand *result, 
10693                                iCode *ic)
10694 {
10695 //  asmop *aop = NULL;
10696   //regs *preg = NULL ;
10697   sym_link *rtype, *retype;
10698   sym_link *ltype, *letype;
10699
10700     FENTRY;
10701     
10702     rtype = operandType(result);
10703     retype= getSpec(rtype);
10704     ltype = operandType(left);
10705     letype= getSpec(ltype);
10706     
10707     pic16_aopOp(left,ic,FALSE);
10708
10709 //    pic16_DumpOp("(left)",left);
10710 //    pic16_DumpOp("(result)",result);
10711
10712     /* if left is rematerialisable and
10713      * result is not bit variable type and
10714      * the left is pointer to data space i.e
10715      * lower 128 bytes of space */
10716     
10717     if (AOP_TYPE(left) == AOP_PCODE
10718       && !IS_BITFIELD(retype)
10719       && DCL_TYPE(ltype) == POINTER) {
10720
10721         genDataPointerGet (left,result,ic);
10722         pic16_freeAsmop(left, NULL, ic, TRUE);
10723         return ;
10724     }
10725     
10726     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10727     pic16_aopOp (result,ic,TRUE);
10728     
10729     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10730
10731 #if 1
10732     if(IS_BITFIELD( retype )
10733       && (SPEC_BLEN(operandType(result))==1)
10734     ) {
10735       iCode *nextic;
10736       pCodeOp *jop;
10737       int bitstrt, bytestrt;
10738
10739         /* if this is bitfield of size 1, see if we are checking the value
10740          * of a single bit in an if-statement,
10741          * if yes, then don't generate usual code, but execute the
10742          * genIfx directly -- VR */
10743
10744         nextic = ic->next;
10745
10746         /* CHECK: if next iCode is IFX
10747          * and current result operand is nextic's conditional operand
10748          * and current result operand live ranges ends at nextic's key number
10749          */
10750         if((nextic->op == IFX)
10751           && (result == IC_COND(nextic))
10752           && (OP_LIVETO(result) == nextic->seq)
10753           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10754           ) {
10755             /* everything is ok then */
10756             /* find a way to optimize the genIfx iCode */
10757
10758             bytestrt = SPEC_BSTR(operandType(result))/8;
10759             bitstrt = SPEC_BSTR(operandType(result))%8;
10760             
10761             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10762
10763             genIfxpCOpJump(nextic, jop);
10764             
10765             pic16_freeAsmop(left, NULL, ic, TRUE);
10766             pic16_freeAsmop(result, NULL, ic, TRUE);
10767             return;
10768         }
10769     }
10770 #endif
10771
10772     /* if bitfield then unpack the bits */
10773     if (IS_BITFIELD(letype)) 
10774       genUnpackBits (result, left, NULL, POINTER);
10775     else {
10776       /* we have can just get the values */
10777       int size = AOP_SIZE(result);
10778       int offset = 0;   
10779         
10780       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10781
10782       pic16_loadFSR0( left, 0 );
10783
10784       while(size--) {
10785         if(size) {
10786           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10787                 pic16_popGet(AOP(result), offset++)));
10788         } else {
10789           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10790                 pic16_popGet(AOP(result), offset++)));
10791         }
10792       }
10793     }
10794
10795 #if 0
10796     /* now some housekeeping stuff */
10797     if (aop) {
10798       /* we had to allocate for this iCode */
10799       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10800       pic16_freeAsmop(NULL,aop,ic,TRUE);
10801     } else { 
10802       /* we did not allocate which means left
10803        * already in a pointer register, then
10804        * if size > 0 && this could be used again
10805        * we have to point it back to where it 
10806        * belongs */
10807       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10808       if (AOP_SIZE(result) > 1
10809         && !OP_SYMBOL(left)->remat
10810         && ( OP_SYMBOL(left)->liveTo > ic->seq
10811             || ic->depth )) {
10812 //        int size = AOP_SIZE(result) - 1;
10813 //        while (size--)
10814 //          pic16_emitcode("dec","%s",rname);
10815         }
10816     }
10817 #endif
10818
10819     /* done */
10820     pic16_freeAsmop(left,NULL,ic,TRUE);
10821     pic16_freeAsmop(result,NULL,ic,TRUE);
10822 }
10823
10824 /*-----------------------------------------------------------------*/
10825 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10826 /*-----------------------------------------------------------------*/
10827 static void genPagedPointerGet (operand *left, 
10828                                operand *result, 
10829                                iCode *ic)
10830 {
10831     asmop *aop = NULL;
10832     regs *preg = NULL ;
10833     char *rname ;
10834     sym_link *rtype, *retype;    
10835
10836     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10837
10838     rtype = operandType(result);
10839     retype= getSpec(rtype);
10840     
10841     pic16_aopOp(left,ic,FALSE);
10842
10843   /* if the value is already in a pointer register
10844        then don't need anything more */
10845     if (!AOP_INPREG(AOP(left))) {
10846         /* otherwise get a free pointer register */
10847         aop = newAsmop(0);
10848         preg = getFreePtr(ic,&aop,FALSE);
10849         pic16_emitcode("mov","%s,%s",
10850                 preg->name,
10851                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10852         rname = preg->name ;
10853     } else
10854         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10855     
10856     pic16_freeAsmop(left,NULL,ic,TRUE);
10857     pic16_aopOp (result,ic,TRUE);
10858
10859     /* if bitfield then unpack the bits */
10860     if (IS_BITFIELD(retype)) 
10861         genUnpackBits (result,left,rname,PPOINTER);
10862     else {
10863         /* we have can just get the values */
10864         int size = AOP_SIZE(result);
10865         int offset = 0 ;        
10866         
10867         while (size--) {
10868             
10869             pic16_emitcode("movx","a,@%s",rname);
10870             pic16_aopPut(AOP(result),"a",offset);
10871             
10872             offset++ ;
10873             
10874             if (size)
10875                 pic16_emitcode("inc","%s",rname);
10876         }
10877     }
10878
10879     /* now some housekeeping stuff */
10880     if (aop) {
10881         /* we had to allocate for this iCode */
10882         pic16_freeAsmop(NULL,aop,ic,TRUE);
10883     } else { 
10884         /* we did not allocate which means left
10885            already in a pointer register, then
10886            if size > 0 && this could be used again
10887            we have to point it back to where it 
10888            belongs */
10889         if (AOP_SIZE(result) > 1 &&
10890             !OP_SYMBOL(left)->remat &&
10891             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10892               ic->depth )) {
10893             int size = AOP_SIZE(result) - 1;
10894             while (size--)
10895                 pic16_emitcode("dec","%s",rname);
10896         }
10897     }
10898
10899     /* done */
10900     pic16_freeAsmop(result,NULL,ic,TRUE);
10901     
10902         
10903 }
10904
10905 #if 0
10906 /* This code is not adjusted to PIC16 and fails utterly.
10907  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10908
10909 /*-----------------------------------------------------------------*/
10910 /* genFarPointerGet - gget value from far space                    */
10911 /*-----------------------------------------------------------------*/
10912 static void genFarPointerGet (operand *left,
10913                               operand *result, iCode *ic)
10914 {
10915     int size, offset ;
10916     sym_link *retype = getSpec(operandType(result));
10917
10918     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10919
10920     pic16_aopOp(left,ic,FALSE);
10921
10922     /* if the operand is already in dptr 
10923     then we do nothing else we move the value to dptr */
10924     if (AOP_TYPE(left) != AOP_STR) {
10925         /* if this is remateriazable */
10926         if (AOP_TYPE(left) == AOP_IMMD)
10927             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10928         else { /* we need to get it byte by byte */
10929             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10930             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10931             if (options.model == MODEL_FLAT24)
10932             {
10933                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10934             }
10935         }
10936     }
10937     /* so dptr know contains the address */
10938     pic16_freeAsmop(left,NULL,ic,TRUE);
10939     pic16_aopOp(result,ic,TRUE);
10940
10941     /* if bit then unpack */
10942     if (IS_BITFIELD(retype)) 
10943         genUnpackBits(result,left,"dptr",FPOINTER);
10944     else {
10945         size = AOP_SIZE(result);
10946         offset = 0 ;
10947
10948         while (size--) {
10949             pic16_emitcode("movx","a,@dptr");
10950             pic16_aopPut(AOP(result),"a",offset++);
10951             if (size)
10952                 pic16_emitcode("inc","dptr");
10953         }
10954     }
10955
10956     pic16_freeAsmop(result,NULL,ic,TRUE);
10957 }
10958 #endif
10959
10960 #if 0
10961 /*-----------------------------------------------------------------*/
10962 /* genCodePointerGet - get value from code space                  */
10963 /*-----------------------------------------------------------------*/
10964 static void genCodePointerGet (operand *left,
10965                                 operand *result, iCode *ic)
10966 {
10967     int size, offset ;
10968     sym_link *retype = getSpec(operandType(result));
10969
10970     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10971
10972     pic16_aopOp(left,ic,FALSE);
10973
10974     /* if the operand is already in dptr 
10975     then we do nothing else we move the value to dptr */
10976     if (AOP_TYPE(left) != AOP_STR) {
10977         /* if this is remateriazable */
10978         if (AOP_TYPE(left) == AOP_IMMD)
10979             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
10980         else { /* we need to get it byte by byte */
10981             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
10982             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
10983             if (options.model == MODEL_FLAT24)
10984             {
10985                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
10986             }
10987         }
10988     }
10989     /* so dptr know contains the address */
10990     pic16_freeAsmop(left,NULL,ic,TRUE);
10991     pic16_aopOp(result,ic,FALSE);
10992
10993     /* if bit then unpack */
10994     if (IS_BITFIELD(retype)) 
10995         genUnpackBits(result,left,"dptr",CPOINTER);
10996     else {
10997         size = AOP_SIZE(result);
10998         offset = 0 ;
10999
11000         while (size--) {
11001             pic16_emitcode("clr","a");
11002             pic16_emitcode("movc","a,@a+dptr");
11003             pic16_aopPut(AOP(result),"a",offset++);
11004             if (size)
11005                 pic16_emitcode("inc","dptr");
11006         }
11007     }
11008
11009     pic16_freeAsmop(result,NULL,ic,TRUE);
11010 }
11011 #endif
11012
11013 #if 0
11014 /*-----------------------------------------------------------------*/
11015 /* genGenPointerGet - gget value from generic pointer space        */
11016 /*-----------------------------------------------------------------*/
11017 static void genGenPointerGet (operand *left,
11018                               operand *result, iCode *ic)
11019 {
11020   int size, offset, lit;
11021   sym_link *retype = getSpec(operandType(result));
11022
11023         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11024         pic16_aopOp(left,ic,FALSE);
11025         pic16_aopOp(result,ic,FALSE);
11026         size = AOP_SIZE(result);
11027
11028         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11029
11030         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11031
11032                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11033                 // load FSR0 from immediate
11034                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11035
11036 //              pic16_loadFSR0( left );
11037
11038                 offset = 0;
11039                 while(size--) {
11040                         if(size) {
11041                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11042                         } else {
11043                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11044                         }
11045                         offset++;
11046                 }
11047                 goto release;
11048
11049         }
11050         else { /* we need to get it byte by byte */
11051                 // set up FSR0 with address from left
11052                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11053                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11054                 
11055                 offset = 0 ;
11056
11057                 while(size--) {
11058                         if(size) {
11059                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11060                         } else {
11061                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11062                         }
11063                         offset++;
11064                 }
11065                 goto release;
11066         }
11067
11068   /* if bit then unpack */
11069         if (IS_BITFIELD(retype)) 
11070                 genUnpackBits(result,left,"BAD",GPOINTER);
11071
11072         release:
11073         pic16_freeAsmop(left,NULL,ic,TRUE);
11074         pic16_freeAsmop(result,NULL,ic,TRUE);
11075
11076 }
11077 #endif
11078
11079
11080 /*-----------------------------------------------------------------*/
11081 /* genGenPointerGet - gget value from generic pointer space        */
11082 /*-----------------------------------------------------------------*/
11083 static void genGenPointerGet (operand *left,
11084                               operand *result, iCode *ic)
11085 {
11086   int size, offset, lit;
11087   sym_link *letype = getSpec(operandType(left));
11088
11089     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11090     pic16_aopOp(left,ic,FALSE);
11091     pic16_aopOp(result,ic,TRUE);
11092     size = AOP_SIZE(result);
11093
11094     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11095   
11096     /* if bit then unpack */
11097     if (IS_BITFIELD(letype)) {
11098       genUnpackBits(result,left,"BAD",GPOINTER);
11099       goto release;
11100     }
11101
11102     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11103
11104       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11105       // load FSR0 from immediate
11106       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11107
11108       werror(W_POSSBUG2, __FILE__, __LINE__);
11109
11110       offset = 0;
11111       while(size--) {
11112         if(size) {
11113           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11114         } else {
11115           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11116         }
11117         offset++;
11118       }
11119
11120       goto release;
11121
11122     } else { /* we need to get it byte by byte */
11123
11124       /* set up WREG:PRODL:FSR0L with address from left */
11125       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11126       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_prodl)));
11127       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 2));
11128       
11129       pic16_callGenericPointerRW(0, size);
11130       
11131       assignResultValue(result, 1);
11132       
11133       goto release;
11134     }
11135
11136 release:
11137   pic16_freeAsmop(left,NULL,ic,TRUE);
11138   pic16_freeAsmop(result,NULL,ic,TRUE);
11139 }
11140
11141 /*-----------------------------------------------------------------*/
11142 /* genConstPointerGet - get value from const generic pointer space */
11143 /*-----------------------------------------------------------------*/
11144 static void genConstPointerGet (operand *left,
11145                                 operand *result, iCode *ic)
11146 {
11147   //sym_link *retype = getSpec(operandType(result));
11148   // symbol *albl = newiTempLabel(NULL);        // patch 15
11149   // symbol *blbl = newiTempLabel(NULL);        //
11150   // PIC_OPCODE poc;                            // patch 15
11151   int size;
11152   int offset = 0;
11153
11154   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11155   pic16_aopOp(left,ic,FALSE);
11156   pic16_aopOp(result,ic,TRUE);
11157   size = AOP_SIZE(result);
11158
11159   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11160
11161   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11162
11163   // set up table pointer
11164   if( (AOP_TYPE(left) == AOP_PCODE) 
11165       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11166           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11167     {
11168       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11169       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11170       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11171       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11172       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11173       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11174   } else {
11175     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
11176     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
11177     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
11178   }
11179
11180   while(size--) {
11181     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11182     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11183     offset++;
11184   }
11185     
11186   pic16_freeAsmop(left,NULL,ic,TRUE);
11187   pic16_freeAsmop(result,NULL,ic,TRUE);
11188 }
11189
11190
11191 /*-----------------------------------------------------------------*/
11192 /* genPointerGet - generate code for pointer get                   */
11193 /*-----------------------------------------------------------------*/
11194 static void genPointerGet (iCode *ic)
11195 {
11196   operand *left, *result ;
11197   sym_link *type, *etype;
11198   int p_type;
11199
11200     FENTRY;
11201     
11202     left = IC_LEFT(ic);
11203     result = IC_RESULT(ic) ;
11204
11205     /* depending on the type of pointer we need to
11206     move it to the correct pointer register */
11207     type = operandType(left);
11208     etype = getSpec(type);
11209
11210 #if 0
11211     if (IS_PTR_CONST(type))
11212 #else
11213     if (IS_CODEPTR(type))
11214 #endif
11215       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11216
11217     /* if left is of type of pointer then it is simple */
11218     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11219       p_type = DCL_TYPE(type);
11220     else {
11221       /* we have to go by the storage class */
11222       p_type = PTR_TYPE(SPEC_OCLS(etype));
11223
11224       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11225
11226       if (SPEC_OCLS(etype)->codesp ) {
11227         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11228         //p_type = CPOINTER ;   
11229       } else
11230       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11231         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11232         /*p_type = FPOINTER ;*/ 
11233       } else
11234       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11235         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11236         /* p_type = PPOINTER; */
11237       } else
11238       if (SPEC_OCLS(etype) == idata ) {
11239         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11240         /* p_type = IPOINTER; */
11241       } else {
11242         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11243         /* p_type = POINTER ; */
11244       }
11245     }
11246
11247     /* now that we have the pointer type we assign
11248     the pointer values */
11249     switch (p_type) {
11250       case POINTER:     
11251       case FPOINTER:
11252       case IPOINTER:
11253         genNearPointerGet (left,result,ic);
11254         break;
11255
11256       case PPOINTER:
11257         genPagedPointerGet(left,result,ic);
11258         break;
11259
11260 #if 0
11261       /* PICs do not support FAR pointers... */
11262       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11263       case FPOINTER:
11264         genFarPointerGet (left,result,ic);
11265         break;
11266 #endif
11267
11268       case CPOINTER:
11269         genConstPointerGet (left,result,ic);
11270         //pic16_emitcodePointerGet (left,result,ic);
11271         break;
11272
11273       case GPOINTER:
11274 #if 0
11275       if (IS_PTR_CONST(type))
11276         genConstPointerGet (left,result,ic);
11277       else
11278 #endif
11279         genGenPointerGet (left,result,ic);
11280       break;
11281
11282     default:
11283       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11284               "genPointerGet: illegal pointer type");
11285     
11286     }
11287 }
11288
11289 /*-----------------------------------------------------------------*/
11290 /* genPackBits - generates code for packed bit storage             */
11291 /*-----------------------------------------------------------------*/
11292 static void genPackBits (sym_link    *etype , operand *result,
11293                          operand *right ,
11294                          char *rname, int p_type)
11295 {
11296   int shCnt = 0 ;
11297   int offset = 0  ;
11298   int rLen = 0 ;
11299   int blen, bstr ;   
11300   sym_link *retype;
11301
11302         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11303         blen = SPEC_BLEN(etype);
11304         bstr = SPEC_BSTR(etype);
11305
11306         retype = getSpec(operandType(right));
11307
11308         if(AOP_TYPE(right) == AOP_LIT) {
11309                 if((blen == 1) && (bstr < 8)) {
11310                   unsigned long lit;
11311                         /* it is a single bit, so use the appropriate bit instructions */
11312
11313                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11314
11315                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11316 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11317                         if(OP_SYMBOL(result)->remat && (p_type == POINTER) && (result)) {
11318                                 /* workaround to reduce the extra lfsr instruction */
11319                                 if(lit) {
11320                                         pic16_emitpcode(POC_BSF,
11321                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11322                                 } else {
11323                                         pic16_emitpcode(POC_BCF,
11324                                                 pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11325                                 }
11326                         } else {
11327                                 pic16_loadFSR0(result, 0);
11328                                 if(lit) {
11329                                         pic16_emitpcode(POC_BSF,
11330                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11331                                 } else {
11332                                         pic16_emitpcode(POC_BCF,
11333                                                 pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11334                                 }
11335                         }
11336         
11337                   return;
11338                 }
11339                 /* move literal to W */
11340                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
11341                 offset++;
11342         } else
11343         if(IS_BITFIELD(retype) 
11344           && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11345           && (blen == 1)) {
11346           int rblen, rbstr;
11347
11348             rblen = SPEC_BLEN( retype );
11349             rbstr = SPEC_BSTR( retype );
11350             
11351
11352             if(IS_BITFIELD(etype)) {
11353               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11354               pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11355             } else {
11356               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11357             }
11358             
11359             pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11360             
11361             if(IS_BITFIELD(etype)) {
11362               pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11363             } else {
11364               pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11365             }
11366
11367             pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11368             
11369             return;
11370         } else {
11371           /* move right to W */
11372           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11373         }
11374
11375         /* if the bit length is less than or   */
11376         /* it exactly fits a byte then         */
11377         if((shCnt=SPEC_BSTR(etype))
11378                 || SPEC_BLEN(etype) <= 8 )  {
11379                 int fsr0_setup = 0;
11380
11381                 if (blen != 8 || bstr != 0) {
11382                   // we need to combine the value with the old value
11383                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11384
11385           DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11386                 SPEC_BSTR(etype), SPEC_BLEN(etype));
11387                 
11388                   /* shift left acc */
11389                   AccLsh(shCnt);
11390
11391                   /* using PRODH as a temporary register here */
11392                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11393
11394                   if (IS_SYMOP(result) && !IS_PTR(operandType (result))/*OP_SYMBOL(result)->remat*/) {
11395                     /* access symbol directly */
11396                     pic16_mov2w (AOP(result), 0);
11397                   } else {
11398                     /* get old value */
11399                     pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11400                   }
11401 #if 1
11402                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11403                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11404                                         (unsigned char)(0xff >> (8-bstr))) ));
11405                   pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11406                 } // if (blen != 8 || bstr != 0)
11407
11408                 /* write new value back */
11409                 if (IS_SYMOP(result) & !IS_PTR(operandType(result))) {
11410                   pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11411                 } else {
11412                   pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11413                }
11414 #endif
11415
11416           return;
11417         }
11418
11419
11420 #if 0
11421         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11422         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11423         exit(-1);
11424 #endif
11425
11426
11427     pic16_loadFSR0(result, 0);                  // load FSR0 with address of result
11428     rLen = SPEC_BLEN(etype)-8;
11429     
11430     /* now generate for lengths greater than one byte */
11431     while (1) {
11432         rLen -= 8 ;
11433         if (rLen <= 0 ) {
11434           mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11435           break ;
11436         }
11437
11438         switch (p_type) {
11439             case POINTER:
11440                   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11441                 break;
11442
11443 /*
11444             case FPOINTER:
11445                 MOVA(l);
11446                 pic16_emitcode("movx","@dptr,a");
11447                 break;
11448
11449             case GPOINTER:
11450                 MOVA(l);
11451                 DEBUGpic16_emitcode(";lcall","__gptrput");
11452                 break;  
11453 */
11454           default:
11455             assert(0);
11456         }   
11457
11458
11459         pic16_mov2w(AOP(right), offset++);
11460     }
11461
11462     /* last last was not complete */
11463     if (rLen)   {
11464         /* save the byte & read byte */
11465         switch (p_type) {
11466             case POINTER:
11467 //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11468                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11469                 break;
11470
11471 /*
11472             case FPOINTER:
11473                 pic16_emitcode ("mov","b,a");
11474                 pic16_emitcode("movx","a,@dptr");
11475                 break;
11476
11477             case GPOINTER:
11478                 pic16_emitcode ("push","b");
11479                 pic16_emitcode ("push","acc");
11480                 pic16_emitcode ("lcall","__gptrget");
11481                 pic16_emitcode ("pop","b");
11482                 break;
11483 */
11484             default:
11485               assert(0);
11486         }
11487         DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11488         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11489         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11490 //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11491 //        pic16_emitcode ("orl","a,b");
11492     }
11493
11494 //    if (p_type == GPOINTER)
11495 //        pic16_emitcode("pop","b");
11496
11497     switch (p_type) {
11498
11499       case POINTER:
11500         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11501 //      pic16_emitcode("mov","@%s,a",rname);
11502         break;
11503 /*
11504       case FPOINTER:
11505         pic16_emitcode("movx","@dptr,a");
11506         break;
11507         
11508       case GPOINTER:
11509         DEBUGpic16_emitcode(";lcall","__gptrput");
11510         break;                  
11511 */
11512       default:
11513         assert(0);
11514     }
11515     
11516 //    pic16_freeAsmop(right, NULL, ic, TRUE);
11517 }
11518 /*-----------------------------------------------------------------*/
11519 /* genDataPointerSet - remat pointer to data space                 */
11520 /*-----------------------------------------------------------------*/
11521 static void genDataPointerSet(operand *right,
11522                               operand *result,
11523                               iCode *ic)
11524 {
11525     int size, offset = 0, resoffset=0 ;
11526
11527     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11528     pic16_aopOp(right,ic,FALSE);
11529
11530     size = AOP_SIZE(right);
11531
11532 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11533
11534 #if 0
11535     if ( AOP_TYPE(result) == AOP_PCODE) {
11536       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11537               AOP(result)->aopu.pcop->name,
11538                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11539               PCOR(AOP(result)->aopu.pcop)->instance:
11540               PCOI(AOP(result)->aopu.pcop)->offset);
11541     }
11542 #endif
11543
11544         if(AOP(result)->aopu.pcop->type == PO_DIR)
11545                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11546
11547         while (size--) {
11548                 if (AOP_TYPE(right) == AOP_LIT) {
11549                   unsigned int lit;
11550
11551                     if(!IS_FLOAT(operandType( right )))
11552                       lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11553                     else {
11554                       union {
11555                         unsigned long lit_int;
11556                         float lit_float;
11557                       } info;
11558         
11559                         /* take care if literal is a float */
11560                         info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11561                         lit = info.lit_int;
11562                     }
11563
11564                     lit = lit >> (8*offset);
11565                     if(lit&0xff) {
11566                       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
11567                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
11568                     } else {
11569                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
11570                     }
11571                 } else {
11572                   pic16_mov2w(AOP(right), offset);
11573                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11574                 }
11575                 offset++;
11576                 resoffset++;
11577         }
11578
11579     pic16_freeAsmop(right,NULL,ic,TRUE);
11580 }
11581
11582
11583
11584 /*-----------------------------------------------------------------*/
11585 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11586 /*-----------------------------------------------------------------*/
11587 static void genNearPointerSet (operand *right,
11588                                operand *result, 
11589                                iCode *ic)
11590 {
11591   asmop *aop = NULL;
11592   sym_link *retype;
11593   sym_link *ptype = operandType(result);
11594   sym_link *resetype;
11595     
11596         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11597         retype= getSpec(operandType(right));
11598         resetype = getSpec(operandType(result));
11599   
11600         pic16_aopOp(result,ic,FALSE);
11601     
11602         /* if the result is rematerializable &
11603          * in data space & not a bit variable */
11604         
11605         /* and result is not a bit variable */
11606         if (AOP_TYPE(result) == AOP_PCODE
11607 //              && AOP_TYPE(result) == AOP_IMMD
11608                 && DCL_TYPE(ptype) == POINTER
11609                 && !IS_BITFIELD(retype)
11610                 && !IS_BITFIELD(resetype)) {
11611
11612                 genDataPointerSet (right,result,ic);
11613                 pic16_freeAsmop(result,NULL,ic,TRUE);
11614           return;
11615         }
11616
11617         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11618         pic16_aopOp(right,ic,FALSE);
11619         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11620
11621         /* if bitfield then unpack the bits */
11622         if (IS_BITFIELD(resetype)) {
11623                 genPackBits (resetype, result, right, NULL, POINTER);
11624         } else {
11625                 /* we have can just get the values */
11626           int size = AOP_SIZE(right);
11627           int offset = 0 ;    
11628
11629             pic16_loadFSR0(result, 0);
11630             
11631                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11632                 while (size--) {
11633                                 if (AOP_TYPE(right) == AOP_LIT) {
11634                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11635                                         if (size) {
11636                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11637                                         } else {
11638                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11639                                         }
11640                                 } else { // no literal
11641                                         if(size) {
11642                                                 pic16_emitpcode(POC_MOVFF,
11643                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11644                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11645                                         } else {
11646                                                 pic16_emitpcode(POC_MOVFF,
11647                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),
11648                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11649                                         }
11650                                 }
11651                         offset++;
11652                 }
11653         }
11654
11655         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11656         /* now some housekeeping stuff */
11657         if (aop) {
11658           /* we had to allocate for this iCode */
11659           pic16_freeAsmop(NULL,aop,ic,TRUE);
11660         } else { 
11661           /* we did not allocate which means left
11662            * already in a pointer register, then
11663            * if size > 0 && this could be used again
11664            * we have to point it back to where it 
11665            * belongs */
11666           DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11667           if (AOP_SIZE(right) > 1
11668             && !OP_SYMBOL(result)->remat
11669             && ( OP_SYMBOL(result)->liveTo > ic->seq
11670             || ic->depth )) {
11671
11672               int size = AOP_SIZE(right) - 1;
11673
11674                 while (size--)
11675                   pic16_emitcode("decf","fsr0,f");
11676                   //pic16_emitcode("dec","%s",rname);
11677             }
11678         }
11679
11680     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11681     /* done */
11682 //release:
11683     pic16_freeAsmop(right,NULL,ic,TRUE);
11684     pic16_freeAsmop(result,NULL,ic,TRUE);
11685 }
11686
11687 /*-----------------------------------------------------------------*/
11688 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11689 /*-----------------------------------------------------------------*/
11690 static void genPagedPointerSet (operand *right,
11691                                operand *result, 
11692                                iCode *ic)
11693 {
11694     asmop *aop = NULL;
11695     regs *preg = NULL ;
11696     char *rname , *l;
11697     sym_link *retype;
11698        
11699     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11700
11701     retype= getSpec(operandType(right));
11702     
11703     pic16_aopOp(result,ic,FALSE);
11704     
11705     /* if the value is already in a pointer register
11706        then don't need anything more */
11707     if (!AOP_INPREG(AOP(result))) {
11708         /* otherwise get a free pointer register */
11709         aop = newAsmop(0);
11710         preg = getFreePtr(ic,&aop,FALSE);
11711         pic16_emitcode("mov","%s,%s",
11712                 preg->name,
11713                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11714         rname = preg->name ;
11715     } else
11716         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11717     
11718     pic16_freeAsmop(result,NULL,ic,TRUE);
11719     pic16_aopOp (right,ic,FALSE);
11720
11721     /* if bitfield then unpack the bits */
11722     if (IS_BITFIELD(retype)) 
11723         genPackBits (retype,result,right,rname,PPOINTER);
11724     else {
11725         /* we have can just get the values */
11726         int size = AOP_SIZE(right);
11727         int offset = 0 ;        
11728         
11729         while (size--) {
11730             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11731             
11732             MOVA(l);
11733             pic16_emitcode("movx","@%s,a",rname);
11734
11735             if (size)
11736                 pic16_emitcode("inc","%s",rname);
11737
11738             offset++;
11739         }
11740     }
11741     
11742     /* now some housekeeping stuff */
11743     if (aop) {
11744         /* we had to allocate for this iCode */
11745         pic16_freeAsmop(NULL,aop,ic,TRUE);
11746     } else { 
11747         /* we did not allocate which means left
11748            already in a pointer register, then
11749            if size > 0 && this could be used again
11750            we have to point it back to where it 
11751            belongs */
11752         if (AOP_SIZE(right) > 1 &&
11753             !OP_SYMBOL(result)->remat &&
11754             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11755               ic->depth )) {
11756             int size = AOP_SIZE(right) - 1;
11757             while (size--)
11758                 pic16_emitcode("dec","%s",rname);
11759         }
11760     }
11761
11762     /* done */
11763     pic16_freeAsmop(right,NULL,ic,TRUE);
11764     
11765         
11766 }
11767
11768 #if 0
11769 /* This code is not adjusted to PIC16 and fails utterly...
11770  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11771
11772 /*-----------------------------------------------------------------*/
11773 /* genFarPointerSet - set value from far space                     */
11774 /*-----------------------------------------------------------------*/
11775 static void genFarPointerSet (operand *right,
11776                               operand *result, iCode *ic)
11777 {
11778     int size, offset ;
11779     sym_link *retype = getSpec(operandType(right));
11780
11781     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11782     pic16_aopOp(result,ic,FALSE);
11783
11784     /* if the operand is already in dptr 
11785     then we do nothing else we move the value to dptr */
11786     if (AOP_TYPE(result) != AOP_STR) {
11787         /* if this is remateriazable */
11788         if (AOP_TYPE(result) == AOP_IMMD)
11789             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11790         else { /* we need to get it byte by byte */
11791             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11792             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11793             if (options.model == MODEL_FLAT24)
11794             {
11795                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11796             }
11797         }
11798     }
11799     /* so dptr know contains the address */
11800     pic16_freeAsmop(result,NULL,ic,TRUE);
11801     pic16_aopOp(right,ic,FALSE);
11802
11803     /* if bit then unpack */
11804     if (IS_BITFIELD(retype)) 
11805         genPackBits(retype,result,right,"dptr",FPOINTER);
11806     else {
11807         size = AOP_SIZE(right);
11808         offset = 0 ;
11809
11810         while (size--) {
11811             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11812             MOVA(l);
11813             pic16_emitcode("movx","@dptr,a");
11814             if (size)
11815                 pic16_emitcode("inc","dptr");
11816         }
11817     }
11818
11819     pic16_freeAsmop(right,NULL,ic,TRUE);
11820 }
11821 #endif
11822
11823 /*-----------------------------------------------------------------*/
11824 /* genGenPointerSet - set value from generic pointer space         */
11825 /*-----------------------------------------------------------------*/
11826 #if 0
11827 static void genGenPointerSet (operand *right,
11828                               operand *result, iCode *ic)
11829 {
11830         int i, size, offset, lit;
11831         sym_link *retype = getSpec(operandType(right));
11832
11833         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11834
11835         pic16_aopOp(result,ic,FALSE);
11836         pic16_aopOp(right,ic,FALSE);
11837         size = AOP_SIZE(right);
11838         offset = 0;
11839
11840         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11841
11842         /* if the operand is already in dptr 
11843                 then we do nothing else we move the value to dptr */
11844         if (AOP_TYPE(result) != AOP_STR) {
11845                 /* if this is remateriazable */
11846                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11847                 // WARNING: anythig until "else" is untested!
11848                 if (AOP_TYPE(result) == AOP_IMMD) {
11849                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11850                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11851                         // load FSR0 from immediate
11852                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11853                         offset = 0;
11854                         while(size--) {
11855                                 if(size) {
11856                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11857                                 } else {
11858                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11859                                 }
11860                                 offset++;
11861                         }
11862                         goto release;
11863                 }
11864                 else { /* we need to get it byte by byte */
11865                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11866                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11867
11868                         // set up FSR0 with address of result
11869                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11870                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11871
11872                         /* hack hack! see if this the FSR. If so don't load W */
11873                         if(AOP_TYPE(right) != AOP_ACC) {
11874
11875                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11876
11877                                 if(AOP_TYPE(right) == AOP_LIT)
11878                                 {
11879                                         // copy literal
11880                                         // note: pic16_popGet handles sign extension
11881                                         for(i=0;i<size;i++) {
11882                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11883                                                 if(i < size-1)
11884                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11885                                                 else
11886                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11887                                         }
11888                                 } else {
11889                                         // copy regs
11890
11891                                         for(i=0;i<size;i++) {
11892                                                 if(i < size-1)
11893                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11894                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11895                                                 else
11896                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11897                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
11898                                         }
11899                                 }
11900                                 goto release;
11901                         } 
11902                         // right = ACC
11903                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11904                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11905                         goto release;
11906         } // if (AOP_TYPE(result) != AOP_IMMD)
11907
11908         } // if (AOP_TYPE(result) != AOP_STR)
11909         /* so dptr know contains the address */
11910
11911
11912         /* if bit then unpack */
11913         if (IS_BITFIELD(retype)) 
11914                 genPackBits(retype,result,right,"dptr",GPOINTER);
11915         else {
11916                 size = AOP_SIZE(right);
11917                 offset = 0 ;
11918
11919                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11920
11921                 // set up FSR0 with address of result
11922                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11923                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11924         
11925                 while (size--) {
11926                         if (AOP_TYPE(right) == AOP_LIT) {
11927                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11928                                 if (size) {
11929                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11930                                 } else {
11931                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11932                                 }
11933                         } else { // no literal
11934                                 if(size) {
11935                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11936                                 } else {
11937                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11938                                 }
11939                         }
11940                         offset++;
11941                 }
11942         }
11943
11944         release:
11945         pic16_freeAsmop(right,NULL,ic,TRUE);
11946         pic16_freeAsmop(result,NULL,ic,TRUE);
11947 }
11948 #endif
11949
11950 static void genGenPointerSet (operand *right,
11951                               operand *result, iCode *ic)
11952 {
11953   int size;
11954   sym_link *retype = getSpec(operandType(result));
11955
11956     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11957
11958     pic16_aopOp(result,ic,FALSE);
11959     pic16_aopOp(right,ic,FALSE);
11960     size = AOP_SIZE(right);
11961
11962     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11963
11964
11965     /* if bit then unpack */
11966     if (IS_BITFIELD(retype)) {
11967 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11968       genPackBits(retype,result,right,"dptr",GPOINTER);
11969       goto release;
11970     }
11971
11972     size = AOP_SIZE(right);
11973
11974     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
11975
11976
11977     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
11978
11979     /* value of right+0 is placed on stack, which will be retrieved
11980      * by the support function this restoring the stack. The important
11981      * thing is that there is no need to manually restore stack pointer
11982      * here */
11983     pushaop(AOP(right), 0);
11984 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
11985     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
11986     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
11987     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
11988     
11989     /* load address to write to in WREG:FSR0H:FSR0L */
11990     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
11991                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
11992     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
11993                                 pic16_popCopyReg(&pic16_pc_prodl)));
11994     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
11995     
11996     pic16_callGenericPointerRW(1, size);
11997
11998 release:
11999     pic16_freeAsmop(right,NULL,ic,TRUE);
12000     pic16_freeAsmop(result,NULL,ic,TRUE);
12001 }
12002
12003 /*-----------------------------------------------------------------*/
12004 /* genPointerSet - stores the value into a pointer location        */
12005 /*-----------------------------------------------------------------*/
12006 static void genPointerSet (iCode *ic)
12007 {    
12008   operand *right, *result ;
12009   sym_link *type, *etype;
12010   int p_type;
12011
12012     FENTRY;
12013
12014     right = IC_RIGHT(ic);
12015     result = IC_RESULT(ic) ;
12016
12017     /* depending on the type of pointer we need to
12018     move it to the correct pointer register */
12019     type = operandType(result);
12020     etype = getSpec(type);
12021     
12022     /* if left is of type of pointer then it is simple */
12023     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12024         p_type = DCL_TYPE(type);
12025     }
12026     else {
12027         /* we have to go by the storage class */
12028         p_type = PTR_TYPE(SPEC_OCLS(etype));
12029
12030 /*      if (SPEC_OCLS(etype)->codesp ) { */
12031 /*          p_type = CPOINTER ;  */
12032 /*      } */
12033 /*      else */
12034 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12035 /*              p_type = FPOINTER ; */
12036 /*          else */
12037 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12038 /*                  p_type = PPOINTER ; */
12039 /*              else */
12040 /*                  if (SPEC_OCLS(etype) == idata ) */
12041 /*                      p_type = IPOINTER ; */
12042 /*                  else */
12043 /*                      p_type = POINTER ; */
12044     }
12045
12046     /* now that we have the pointer type we assign
12047     the pointer values */
12048     switch (p_type) {
12049       case POINTER:
12050       case FPOINTER:
12051       case IPOINTER:
12052         genNearPointerSet (right,result,ic);
12053         break;
12054
12055       case PPOINTER:
12056         genPagedPointerSet (right,result,ic);
12057         break;
12058
12059 #if 0
12060       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12061       case FPOINTER:
12062         genFarPointerSet (right,result,ic);
12063         break;
12064 #endif
12065         
12066       case GPOINTER:
12067         genGenPointerSet (right,result,ic);
12068         break;
12069
12070       default:
12071         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12072           "genPointerSet: illegal pointer type");
12073     }
12074 }
12075
12076 /*-----------------------------------------------------------------*/
12077 /* genIfx - generate code for Ifx statement                        */
12078 /*-----------------------------------------------------------------*/
12079 static void genIfx (iCode *ic, iCode *popIc)
12080 {
12081   operand *cond = IC_COND(ic);
12082   int isbit =0;
12083
12084     FENTRY;
12085
12086     pic16_aopOp(cond,ic,FALSE);
12087
12088     /* get the value into acc */
12089     if (AOP_TYPE(cond) != AOP_CRY)
12090       pic16_toBoolean(cond);
12091     else
12092       isbit = 1;
12093     /* the result is now in the accumulator */
12094     pic16_freeAsmop(cond,NULL,ic,TRUE);
12095
12096     /* if there was something to be popped then do it */
12097     if (popIc)
12098       genIpop(popIc);
12099
12100     /* if the condition is  a bit variable */
12101     if (isbit && IS_ITEMP(cond) && 
12102         SPIL_LOC(cond)) {
12103       genIfxJump(ic,"c");
12104       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12105     } else {
12106       if (isbit && !IS_ITEMP(cond))
12107         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12108         else
12109         genIfxJump(ic,"a");
12110     }
12111     ic->generated = 1;
12112 }
12113
12114 /*-----------------------------------------------------------------*/
12115 /* genAddrOf - generates code for address of                       */
12116 /*-----------------------------------------------------------------*/
12117 static void genAddrOf (iCode *ic)
12118 {
12119   operand *result, *left;
12120   int size;
12121   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12122   pCodeOp *pcop0, *pcop1, *pcop2;
12123
12124     FENTRY;
12125
12126     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12127
12128     sym = OP_SYMBOL( IC_LEFT(ic) );
12129     
12130     if(sym->onStack) {
12131       /* get address of symbol on stack */
12132       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12133 #if 0
12134       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12135                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12136 #endif
12137
12138       // operands on stack are accessible via "FSR2 + index" with index
12139       // starting at 2 for arguments and growing from 0 downwards for
12140       // local variables (index == 0 is not assigned so we add one here)
12141       {
12142         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12143         if (soffs <= 0) {
12144           assert (soffs < 0);
12145           soffs++;
12146         } // if
12147         DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12148         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12149         pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12150         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12151         pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12152         pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12153         pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12154       }
12155
12156       goto release;
12157     }
12158         
12159 //      if(pic16_debug_verbose) {
12160 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12161 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12162 //      }
12163         
12164     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12165     size = AOP_SIZE(IC_RESULT(ic));
12166
12167     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12168     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12169     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12170         
12171     if (size == 3) {
12172       pic16_emitpcode(POC_MOVLW, pcop0);
12173       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12174       pic16_emitpcode(POC_MOVLW, pcop1);
12175       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12176       pic16_emitpcode(POC_MOVLW, pcop2);
12177       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12178     } else
12179     if (size == 2) {
12180       pic16_emitpcode(POC_MOVLW, pcop0);
12181       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12182       pic16_emitpcode(POC_MOVLW, pcop1);
12183     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12184     } else {
12185       pic16_emitpcode(POC_MOVLW, pcop0);
12186       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12187     }
12188
12189     pic16_freeAsmop(left, NULL, ic, FALSE);
12190 release:
12191     pic16_freeAsmop(result,NULL,ic,TRUE);
12192 }
12193
12194
12195 #if 0
12196 /*-----------------------------------------------------------------*/
12197 /* genFarFarAssign - assignment when both are in far space         */
12198 /*-----------------------------------------------------------------*/
12199 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12200 {
12201     int size = AOP_SIZE(right);
12202     int offset = 0;
12203     char *l ;
12204     /* first push the right side on to the stack */
12205     while (size--) {
12206         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12207         MOVA(l);
12208         pic16_emitcode ("push","acc");
12209     }
12210     
12211     pic16_freeAsmop(right,NULL,ic,FALSE);
12212     /* now assign DPTR to result */
12213     pic16_aopOp(result,ic,FALSE);
12214     size = AOP_SIZE(result);
12215     while (size--) {
12216         pic16_emitcode ("pop","acc");
12217         pic16_aopPut(AOP(result),"a",--offset);
12218     }
12219     pic16_freeAsmop(result,NULL,ic,FALSE);
12220         
12221 }
12222 #endif
12223
12224 /*-----------------------------------------------------------------*/
12225 /* genAssign - generate code for assignment                        */
12226 /*-----------------------------------------------------------------*/
12227 static void genAssign (iCode *ic)
12228 {
12229   operand *result, *right;
12230   int size, offset,know_W;
12231   unsigned long lit = 0L;
12232
12233   result = IC_RESULT(ic);
12234   right  = IC_RIGHT(ic) ;
12235
12236   FENTRY;
12237   
12238   /* if they are the same */
12239   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12240     return ;
12241
12242   /* reversed order operands are aopOp'ed so that result operand
12243    * is effective in case right is a stack symbol. This maneauver
12244    * allows to use the _G.resDirect flag later */
12245   pic16_aopOp(result,ic,TRUE);
12246   pic16_aopOp(right,ic,FALSE);
12247
12248   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12249
12250   /* if they are the same registers */
12251   if (pic16_sameRegs(AOP(right),AOP(result)))
12252     goto release;
12253
12254   /* if the result is a bit */
12255   if (AOP_TYPE(result) == AOP_CRY) {
12256     /* if the right size is a literal then
12257        we know what the value is */
12258     if (AOP_TYPE(right) == AOP_LIT) {
12259           
12260       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12261                   pic16_popGet(AOP(result),0));
12262
12263       if (((int) operandLitValue(right))) 
12264         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12265                        AOP(result)->aopu.aop_dir,
12266                        AOP(result)->aopu.aop_dir);
12267       else
12268         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12269                        AOP(result)->aopu.aop_dir,
12270                        AOP(result)->aopu.aop_dir);
12271       goto release;
12272     }
12273
12274     /* the right is also a bit variable */
12275     if (AOP_TYPE(right) == AOP_CRY) {
12276       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12277       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12278       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12279
12280       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12281                      AOP(result)->aopu.aop_dir,
12282                      AOP(result)->aopu.aop_dir);
12283       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
12284                      AOP(right)->aopu.aop_dir,
12285                      AOP(right)->aopu.aop_dir);
12286       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12287                      AOP(result)->aopu.aop_dir,
12288                      AOP(result)->aopu.aop_dir);
12289       goto release ;
12290     }
12291
12292     /* we need to or */
12293     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12294     pic16_toBoolean(right);
12295     emitSKPZ;
12296     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12297     //pic16_aopPut(AOP(result),"a",0);
12298     goto release ;
12299   }
12300
12301   /* bit variables done */
12302   /* general case */
12303   size = AOP_SIZE(result);
12304   offset = 0 ;
12305
12306   if(AOP_TYPE(right) == AOP_LIT) {
12307         if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12308                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12309         else{
12310            union {
12311               unsigned long lit_int;
12312               float lit_float;
12313             } info;
12314         
12315
12316               if(IS_FIXED16X16(operandType(right))) {
12317                 lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12318               } else {
12319                 /* take care if literal is a float */
12320                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12321                 lit = info.lit_int;
12322               }
12323         }
12324   }
12325
12326 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12327 //                      sizeof(unsigned long int), sizeof(float));
12328
12329
12330   if (AOP_TYPE(right) == AOP_REG) {
12331     DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12332     while (size--) {
12333       pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12334     } // while
12335     goto release;
12336   }
12337
12338   /* when do we have to read the program memory?
12339    * - if right itself is a symbol in code space
12340    *   (we don't care what it points to if it's a pointer)
12341    * - AND right is not a function (we would want its address)
12342    */
12343   if(AOP_TYPE(right) != AOP_LIT
12344         && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12345         && !IS_FUNC(OP_SYM_TYPE(right))
12346         && !IS_ITEMP(right))
12347   {
12348         DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12349         fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12350
12351         // set up table pointer
12352         if(is_LitOp(right)) {
12353 //              fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12354                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12355                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12356                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12357                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12358                 pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12359                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12360         } else {
12361 //              fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12362                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12363                                 pic16_popCopyReg(&pic16_pc_tblptrl)));
12364                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12365                                 pic16_popCopyReg(&pic16_pc_tblptrh)));
12366                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12367                                 pic16_popCopyReg(&pic16_pc_tblptru)));
12368         }
12369
12370         /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12371         size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12372         while(size--) {
12373                 pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12374                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12375                         pic16_popGet(AOP(result),offset)));
12376                 offset++;
12377         }
12378
12379         /* FIXME: for pointers we need to extend differently (according
12380          * to pointer type DATA/CODE/EEPROM/... :*/
12381         size = getSize(OP_SYM_TYPE(right));
12382         if(AOP_SIZE(result) > size) {
12383                 size = AOP_SIZE(result) - size;
12384                 while(size--) {
12385                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12386                         offset++;
12387                 }
12388         }
12389         goto release;
12390   }
12391
12392   if (AOP_TYPE(right) == AOP_LIT && IS_SYMOP(result) && IS_GENPTR(OP_SYM_TYPE(result)))
12393   {
12394     /* Arrg -- a literal is cast into a generic pointer: how shall we decide which TAG
12395      *         to assign (__data, __code, __eeprom, ???)??? */
12396     fprintf (stderr, "%s:%u(%s): creating generic pointer from literal defaults to __data TYPE*.\n\tPlease explicitly cast to (__data|__code) TYPE* in line %u if neccessary!\n",
12397         __FILE__, __LINE__, __FUNCTION__, ic->lineno);
12398     /* assume __data space */
12399     lit = (lit & 0x00ffff) | 0x800000;
12400     //exit (-1);
12401   }
12402
12403
12404 #if 0
12405 /* VR - What is this?! */
12406   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12407     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12408     if(aopIdx(AOP(result),0) == 4) {
12409
12410       /* this is a workaround to save value of right into wreg too,
12411        * value of wreg is going to be used later */
12412       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12413       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12414       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12415       goto release;
12416     } else
12417 //      assert(0);
12418       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12419   }
12420 #endif
12421
12422   know_W=-1;
12423   while (size--) {
12424   DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12425     if(AOP_TYPE(right) == AOP_LIT) {
12426       if(lit&0xff) {
12427         if(know_W != (lit&0xff))
12428           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12429         know_W = lit&0xff;
12430         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12431       } else
12432         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12433
12434       lit >>= 8;
12435
12436     } else if (AOP_TYPE(right) == AOP_CRY) {
12437       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12438       if(offset == 0) {
12439         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12440         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12441         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12442       }
12443     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12444         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12445         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12446     } else {
12447       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12448
12449       if(!_G.resDirect)         /* use this aopForSym feature */
12450         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12451     }
12452             
12453     offset++;
12454   }
12455   
12456  release:
12457   pic16_freeAsmop (right,NULL,ic,FALSE);
12458   pic16_freeAsmop (result,NULL,ic,TRUE);
12459 }   
12460
12461 /*-----------------------------------------------------------------*/
12462 /* genJumpTab - generates code for jump table                       */
12463 /*-----------------------------------------------------------------*/
12464 static void genJumpTab (iCode *ic)
12465 {
12466   symbol *jtab;
12467   char *l;
12468   pCodeOp *jt_offs;
12469   pCodeOp *jt_offs_hi;
12470   pCodeOp *jt_label;
12471
12472     FENTRY;
12473
12474     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12475     /* get the condition into accumulator */
12476     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12477     MOVA(l);
12478     /* multiply by three */
12479     pic16_emitcode("add","a,acc");
12480     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12481
12482     jtab = newiTempLabel(NULL);
12483     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12484     pic16_emitcode("jmp","@a+dptr");
12485     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12486
12487 #if 0
12488     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12489     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12490     emitSKPNC;
12491     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12492     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12493     pic16_emitpLabel(jtab->key);
12494
12495 #else
12496
12497     jt_offs = pic16_popGetTempReg(0);
12498     jt_offs_hi = pic16_popGetTempReg(1);
12499     jt_label = pic16_popGetLabel (jtab->key);
12500     //fprintf (stderr, "Creating jump table...\n");
12501
12502     // calculate offset into jump table (idx * sizeof (GOTO))
12503     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12504     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12505     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12506     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12507     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12508     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12509     pic16_emitpcode(POC_MOVWF , jt_offs);
12510
12511     // prepare PCLATx (set to first entry in jump table)
12512     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12513     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12514     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12515     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12516     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12517
12518     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12519     pic16_emitpcode(POC_ADDWF , jt_offs);
12520     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12521     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12522     emitSKPNC;
12523     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12524
12525     // release temporaries and prepare jump into table (new PCL --> WREG)
12526     pic16_emitpcode(POC_MOVFW , jt_offs);
12527     pic16_popReleaseTempReg (jt_offs_hi, 1);
12528     pic16_popReleaseTempReg (jt_offs, 0);
12529
12530     // jump into the table
12531     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12532
12533     pic16_emitpLabelFORCE(jtab->key);
12534 #endif
12535
12536     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12537 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12538
12539     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12540     /* now generate the jump labels */
12541     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12542          jtab = setNextItem(IC_JTLABELS(ic))) {
12543 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12544         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12545         
12546     }
12547     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12548
12549 }
12550
12551 /*-----------------------------------------------------------------*/
12552 /* genMixedOperation - gen code for operators between mixed types  */
12553 /*-----------------------------------------------------------------*/
12554 /*
12555   TSD - Written for the PIC port - but this unfortunately is buggy.
12556   This routine is good in that it is able to efficiently promote 
12557   types to different (larger) sizes. Unfortunately, the temporary
12558   variables that are optimized out by this routine are sometimes
12559   used in other places. So until I know how to really parse the 
12560   iCode tree, I'm going to not be using this routine :(.
12561 */
12562 static int genMixedOperation (iCode *ic)
12563 {
12564 #if 0
12565   operand *result = IC_RESULT(ic);
12566   sym_link *ctype = operandType(IC_LEFT(ic));
12567   operand *right = IC_RIGHT(ic);
12568   int ret = 0;
12569   int big,small;
12570   int offset;
12571
12572   iCode *nextic;
12573   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12574
12575   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12576
12577   nextic = ic->next;
12578   if(!nextic)
12579     return 0;
12580
12581   nextright = IC_RIGHT(nextic);
12582   nextleft  = IC_LEFT(nextic);
12583   nextresult = IC_RESULT(nextic);
12584
12585   pic16_aopOp(right,ic,FALSE);
12586   pic16_aopOp(result,ic,FALSE);
12587   pic16_aopOp(nextright,  nextic, FALSE);
12588   pic16_aopOp(nextleft,   nextic, FALSE);
12589   pic16_aopOp(nextresult, nextic, FALSE);
12590
12591   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12592
12593     operand *t = right;
12594     right = nextright;
12595     nextright = t; 
12596
12597     pic16_emitcode(";remove right +","");
12598
12599   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12600 /*
12601     operand *t = right;
12602     right = nextleft;
12603     nextleft = t; 
12604 */
12605     pic16_emitcode(";remove left +","");
12606   } else
12607     return 0;
12608
12609   big = AOP_SIZE(nextleft);
12610   small = AOP_SIZE(nextright);
12611
12612   switch(nextic->op) {
12613
12614   case '+':
12615     pic16_emitcode(";optimize a +","");
12616     /* if unsigned or not an integral type */
12617     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12618       pic16_emitcode(";add a bit to something","");
12619     } else {
12620
12621       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12622
12623       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12624         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12625         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12626       } else
12627         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12628
12629       offset = 0;
12630       while(--big) {
12631
12632         offset++;
12633
12634         if(--small) {
12635           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12636             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12637             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12638           }
12639
12640           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12641           emitSKPNC;
12642           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12643                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12644                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12645           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12646           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12647
12648         } else {
12649           pic16_emitcode("rlf","known_zero,w");
12650
12651           /*
12652             if right is signed
12653               btfsc  right,7
12654                addlw ff
12655           */
12656           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12657             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12658             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12659           } else {
12660             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12661           }
12662         }
12663       }
12664       ret = 1;
12665     }
12666   }
12667   ret = 1;
12668
12669 release:
12670   pic16_freeAsmop(right,NULL,ic,TRUE);
12671   pic16_freeAsmop(result,NULL,ic,TRUE);
12672   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12673   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12674   if(ret)
12675     nextic->generated = 1;
12676
12677   return ret;
12678 #else
12679   return 0;
12680 #endif
12681 }
12682 /*-----------------------------------------------------------------*/
12683 /* genCast - gen code for casting                                  */
12684 /*-----------------------------------------------------------------*/
12685 static void genCast (iCode *ic)
12686 {
12687   operand *result = IC_RESULT(ic);
12688   sym_link *ctype = operandType(IC_LEFT(ic));
12689   sym_link *rtype = operandType(IC_RIGHT(ic));
12690   sym_link *restype = operandType(IC_RESULT(ic));
12691   operand *right = IC_RIGHT(ic);
12692   int size, offset ;
12693
12694
12695     FENTRY;
12696
12697         /* if they are equivalent then do nothing */
12698 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12699 //              return ;
12700
12701         pic16_aopOp(result,ic,FALSE);
12702         pic16_aopOp(right,ic,FALSE) ;
12703
12704         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12705
12706
12707         /* if the result is a bit */
12708         if (AOP_TYPE(result) == AOP_CRY) {
12709         
12710                 /* if the right size is a literal then
12711                  * we know what the value is */
12712                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12713
12714                 if (AOP_TYPE(right) == AOP_LIT) {
12715                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12716                                 pic16_popGet(AOP(result),0));
12717
12718                         if (((int) operandLitValue(right))) 
12719                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12720                                         AOP(result)->aopu.aop_dir,
12721                                         AOP(result)->aopu.aop_dir);
12722                         else
12723                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12724                                         AOP(result)->aopu.aop_dir,
12725                                         AOP(result)->aopu.aop_dir);
12726                         goto release;
12727                 }
12728
12729                 /* the right is also a bit variable */
12730                 if (AOP_TYPE(right) == AOP_CRY) {
12731                         emitCLRC;
12732                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12733
12734                         pic16_emitcode("clrc","");
12735                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12736                                 AOP(right)->aopu.aop_dir,
12737                                 AOP(right)->aopu.aop_dir);
12738                         pic16_aopPut(AOP(result),"c",0);
12739                         goto release ;
12740                 }
12741
12742                 /* we need to or */
12743                 if (AOP_TYPE(right) == AOP_REG) {
12744                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12745                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12746                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12747                 }
12748                 pic16_toBoolean(right);
12749                 pic16_aopPut(AOP(result),"a",0);
12750                 goto release ;
12751         }
12752
12753         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12754           int offset = 1;
12755
12756                 size = AOP_SIZE(result);
12757
12758                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12759
12760                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12761                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12762                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12763
12764                 while (size--)
12765                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12766
12767                 goto release;
12768         }
12769
12770         if(IS_BITFIELD(getSpec(restype))
12771           && IS_BITFIELD(getSpec(rtype))) {
12772           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12773         }
12774         
12775         /* port from pic14 to cope with generic pointers */
12776         if (IS_PTR(restype))
12777         {
12778           operand *result = IC_RESULT(ic);
12779           //operand *left = IC_LEFT(ic);
12780           operand *right = IC_RIGHT(ic);
12781           int tag = 0xff;
12782           
12783           /* copy common part */
12784           int max, size = AOP_SIZE(result);
12785           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12786           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12787
12788           /* warn if we discard generic opinter tag */
12789           if (!IS_GENPTR(restype) && IS_GENPTR(rtype) && (AOP_SIZE(result) < AOP_SIZE(right)))
12790           {
12791             //fprintf (stderr, "%s:%u: discarding generic pointer type tag\n", __FUNCTION__, __LINE__);
12792           } // if
12793
12794           max = size;
12795           while (size--)
12796           {
12797             pic16_mov2w (AOP(right), size);
12798             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12799           } // while
12800           pic16_addSign(result, max, 0);
12801
12802           /* upcast into generic pointer type? */
12803           if (IS_GENPTR(restype) && !IS_GENPTR(rtype))
12804           {
12805             //fprintf (stderr, "%s:%u: must determine pointer type (IS_PTR: %d, DCL_TYPE: %d)\n", __FUNCTION__, __LINE__, IS_PTR(rtype), IS_PTR(rtype) ? DCL_TYPE(rtype) : 0);
12806             if (IS_PTR(rtype))
12807             {
12808               switch (DCL_TYPE(rtype))
12809               {
12810               case POINTER:     /* __data */
12811               case FPOINTER:    /* __data */
12812                 assert (AOP_SIZE(right) == 2);
12813                 tag = 0x80;
12814                 break;
12815
12816               case CPOINTER:    /* __code */
12817                 assert (AOP_SIZE(right) == 2);
12818                 tag = 0x00;
12819                 break;
12820                 
12821               case GPOINTER:    /* unknown destination, __data or __code */
12822                 assert (AOP_SIZE(right) == 3);
12823                 /* tag taken from right operand */
12824                 break;
12825                 
12826               default:
12827                 assert (!"unhandled pointer type");
12828               } // switch
12829             } else {
12830               /* convert other values into pointers to __data space */
12831               fprintf (stderr, "%s:%u(%s): creating generic pointer from non-pointer type -- assuming __data space\n", __FILE__, __LINE__, __FUNCTION__);
12832               tag = 0x80;
12833             }
12834
12835             assert (AOP_SIZE(result) == 3);
12836             if (tag == 0) {
12837               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 2));
12838             } else {
12839               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(tag));
12840               pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), 2));
12841             }
12842           } // if
12843           goto release;
12844         }
12845
12846         /* if they are the same size : or less */
12847         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12848
12849                 /* if they are in the same place */
12850                 if (pic16_sameRegs(AOP(right),AOP(result)))
12851                         goto release;
12852
12853                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12854 #if 0
12855                 if (IS_PTR_CONST(rtype))
12856 #else
12857                 if (IS_CODEPTR(rtype))
12858 #endif
12859                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12860
12861 #if 0
12862                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12863 #else
12864                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12865 #endif
12866                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12867
12868 #if 0
12869                 if(AOP_TYPE(right) == AOP_IMMD) {
12870                   pCodeOp *pcop0, *pcop1, *pcop2;
12871                   symbol *sym = OP_SYMBOL( right );
12872
12873                         size = AOP_SIZE(result);
12874                         /* low */
12875                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12876                         /* high */
12877                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12878                         /* upper */
12879                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12880         
12881                         if (size == 3) {
12882                                 pic16_emitpcode(POC_MOVLW, pcop0);
12883                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12884                                 pic16_emitpcode(POC_MOVLW, pcop1);
12885                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12886                                 pic16_emitpcode(POC_MOVLW, pcop2);
12887                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12888                         } else
12889                         if (size == 2) {
12890                                 pic16_emitpcode(POC_MOVLW, pcop0);
12891                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12892                                 pic16_emitpcode(POC_MOVLW, pcop1);
12893                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12894                         } else {
12895                                 pic16_emitpcode(POC_MOVLW, pcop0);
12896                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12897                         }
12898                 } else
12899 #endif
12900                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12901                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
12902                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12903                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
12904                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12905                         if(AOP_SIZE(result) <2)
12906                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
12907                 } else {
12908                         /* if they in different places then copy */
12909                         size = AOP_SIZE(result);
12910                         offset = 0 ;
12911                         while (size--) {
12912                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12913                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12914                                 offset++;
12915                         }
12916                 }
12917                 goto release;
12918         }
12919
12920         /* if the result is of type pointer */
12921         if (IS_PTR(ctype)) {
12922           int p_type;
12923           sym_link *type = operandType(right);
12924           sym_link *etype = getSpec(type);
12925
12926                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
12927
12928                 /* pointer to generic pointer */
12929                 if (IS_GENPTR(ctype)) {
12930                   char *l = zero;
12931             
12932                         if (IS_PTR(type)) 
12933                                 p_type = DCL_TYPE(type);
12934                         else {
12935                 /* we have to go by the storage class */
12936                 p_type = PTR_TYPE(SPEC_OCLS(etype));
12937
12938 /*              if (SPEC_OCLS(etype)->codesp )  */
12939 /*                  p_type = CPOINTER ;  */
12940 /*              else */
12941 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12942 /*                      p_type = FPOINTER ; */
12943 /*                  else */
12944 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12945 /*                          p_type = PPOINTER; */
12946 /*                      else */
12947 /*                          if (SPEC_OCLS(etype) == idata ) */
12948 /*                              p_type = IPOINTER ; */
12949 /*                          else */
12950 /*                              p_type = POINTER ; */
12951             }
12952                 
12953             /* the first two bytes are known */
12954       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
12955             size = GPTRSIZE - 1; 
12956             offset = 0 ;
12957             while (size--) {
12958               if(offset < AOP_SIZE(right)) {
12959                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
12960                 pic16_mov2f(AOP(result), AOP(right), offset);
12961 /*
12962                 if ((AOP_TYPE(right) == AOP_PCODE) && 
12963                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
12964                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12965                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12966                 } else { 
12967                   
12968                   pic16_aopPut(AOP(result),
12969                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
12970                          offset);
12971                 }
12972 */
12973               } else 
12974                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
12975               offset++;
12976             }
12977             /* the last byte depending on type */
12978             switch (p_type) {
12979             case IPOINTER:
12980             case POINTER:
12981                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
12982                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
12983 //              pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
12984                 break;
12985
12986             case CPOINTER:
12987                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
12988                 break;
12989
12990             case FPOINTER:
12991               pic16_emitcode(";BUG!? ","%d",__LINE__);
12992                 l = one;
12993                 break;
12994             case PPOINTER:
12995               pic16_emitcode(";BUG!? ","%d",__LINE__);
12996                 l = "#0x03";
12997                 break;
12998
12999             case GPOINTER:
13000                 if (GPTRSIZE > AOP_SIZE(right)) {
13001                   // assume data pointer... THIS MIGHT BE WRONG!
13002                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
13003                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), GPTRSIZE - 1));
13004                 } else {
13005                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13006                 }
13007               break;
13008               
13009             default:
13010                 /* this should never happen */
13011                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13012                        "got unknown pointer type");
13013                 exit(1);
13014             }
13015             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13016             goto release ;
13017         }
13018         
13019         
13020         assert( 0 );
13021         /* just copy the pointers */
13022         size = AOP_SIZE(result);
13023         offset = 0 ;
13024         while (size--) {
13025             pic16_aopPut(AOP(result),
13026                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13027                    offset);
13028             offset++;
13029         }
13030         goto release ;
13031     }
13032     
13033
13034
13035     /* so we now know that the size of destination is greater
13036     than the size of the source.
13037     Now, if the next iCode is an operator then we might be
13038     able to optimize the operation without performing a cast.
13039     */
13040     if(genMixedOperation(ic))
13041       goto release;
13042
13043     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13044     
13045     /* we move to result for the size of source */
13046     size = AOP_SIZE(right);
13047     offset = 0 ;
13048
13049     while (size--) {
13050       if(!_G.resDirect)
13051         pic16_mov2f(AOP(result), AOP(right), offset);
13052       offset++;
13053     }
13054
13055     /* now depending on the sign of the destination */
13056     size = AOP_SIZE(result) - AOP_SIZE(right);
13057     /* if unsigned or not an integral type */
13058     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13059       while (size--)
13060         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13061     } else {
13062       /* we need to extend the sign :( */
13063
13064       if(size == 1) {
13065         /* Save one instruction of casting char to int */
13066         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13067         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13068         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13069       } else {
13070         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13071
13072         if(offset)
13073           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13074         else
13075           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13076         
13077         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13078
13079         while (size--)
13080           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13081       }
13082     }
13083
13084 release:
13085     pic16_freeAsmop(right,NULL,ic,TRUE);
13086     pic16_freeAsmop(result,NULL,ic,TRUE);
13087
13088 }
13089
13090 /*-----------------------------------------------------------------*/
13091 /* genDjnz - generate decrement & jump if not zero instrucion      */
13092 /*-----------------------------------------------------------------*/
13093 static int genDjnz (iCode *ic, iCode *ifx)
13094 {
13095     symbol *lbl, *lbl1;
13096     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13097
13098     if (!ifx)
13099         return 0;
13100     
13101     /* if the if condition has a false label
13102        then we cannot save */
13103     if (IC_FALSE(ifx))
13104         return 0;
13105
13106     /* if the minus is not of the form 
13107        a = a - 1 */
13108     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13109         !IS_OP_LITERAL(IC_RIGHT(ic)))
13110         return 0;
13111
13112     if (operandLitValue(IC_RIGHT(ic)) != 1)
13113         return 0;
13114
13115     /* if the size of this greater than one then no
13116        saving */
13117     if (getSize(operandType(IC_RESULT(ic))) > 1)
13118         return 0;
13119
13120     /* otherwise we can save BIG */
13121     lbl = newiTempLabel(NULL);
13122     lbl1= newiTempLabel(NULL);
13123
13124     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13125     
13126     if (IS_AOP_PREG(IC_RESULT(ic))) {
13127         pic16_emitcode("dec","%s",
13128                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13129         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13130         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13131     } else {    
13132
13133
13134       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13135       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13136
13137       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13138       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13139
13140     }
13141     
13142     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13143     ifx->generated = 1;
13144     return 1;
13145 }
13146
13147 /*-----------------------------------------------------------------*/
13148 /* genReceive - generate code for a receive iCode                  */
13149 /*-----------------------------------------------------------------*/
13150 static void genReceive (iCode *ic)
13151 {    
13152
13153   FENTRY;
13154
13155 #if 0
13156   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13157         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13158 #endif
13159 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13160
13161   if (isOperandInFarSpace(IC_RESULT(ic))
13162       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13163           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13164
13165     int size = getSize(operandType(IC_RESULT(ic)));
13166     int offset =  pic16_fReturnSizePic - size;
13167
13168       assert( 0 );
13169       while (size--) {
13170         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13171                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13172                       offset++;
13173         }
13174
13175       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13176
13177       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13178       size = AOP_SIZE(IC_RESULT(ic));
13179       offset = 0;
13180       while (size--) {
13181         pic16_emitcode ("pop","acc");
13182         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13183       }
13184   } else {
13185     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13186     _G.accInUse++;
13187     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13188     _G.accInUse--;
13189
13190     /* set pseudo stack pointer to where it should be - dw*/
13191     GpsuedoStkPtr = ic->parmBytes;
13192
13193     /* setting GpsuedoStkPtr has side effects here: */
13194     assignResultValue(IC_RESULT(ic), 0);
13195   }
13196
13197   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13198 }
13199
13200 /*-----------------------------------------------------------------*/
13201 /* genDummyRead - generate code for dummy read of volatiles        */
13202 /*-----------------------------------------------------------------*/
13203 static void
13204 genDummyRead (iCode * ic)
13205 {
13206   operand *op;
13207   int i;
13208
13209   op = IC_RIGHT(ic);
13210   if (op && IS_SYMOP(op)) {
13211     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13212       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13213       return;
13214     }
13215     pic16_aopOp (op, ic, FALSE);
13216     for (i=0; i < AOP_SIZE(op); i++) {
13217       // may need to protect this from the peepholer -- this is not nice but works...
13218       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13219       pic16_mov2w (AOP(op),i);
13220       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13221     } // for i
13222     pic16_freeAsmop (op, NULL, ic, TRUE);
13223   } else if (op) {
13224     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13225   } // if
13226 }
13227
13228 /*-----------------------------------------------------------------*/
13229 /* genpic16Code - generate code for pic16 based controllers        */
13230 /*-----------------------------------------------------------------*/
13231 /*
13232  * At this point, ralloc.c has gone through the iCode and attempted
13233  * to optimize in a way suitable for a PIC. Now we've got to generate
13234  * PIC instructions that correspond to the iCode.
13235  *
13236  * Once the instructions are generated, we'll pass through both the
13237  * peep hole optimizer and the pCode optimizer.
13238  *-----------------------------------------------------------------*/
13239
13240 void genpic16Code (iCode *lic)
13241 {
13242   iCode *ic;
13243   int cln = 0;
13244
13245     lineHead = lineCurr = NULL;
13246
13247     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13248     pic16_addpBlock(pb);
13249
13250 #if 0
13251     /* if debug information required */
13252     if (options.debug && currFunc) {
13253       if (currFunc) {
13254         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13255       }
13256     }
13257 #endif
13258
13259     for (ic = lic ; ic ; ic = ic->next ) {
13260
13261       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13262       if ( cln != ic->lineno ) {
13263         if ( options.debug ) {
13264           debugFile->writeCLine (ic);
13265         }
13266         
13267         if(!options.noCcodeInAsm) {
13268           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13269               printCLine(ic->filename, ic->lineno)));
13270         }
13271
13272         cln = ic->lineno ;
13273       }
13274         
13275       if(options.iCodeInAsm) {
13276         char *l;
13277
13278           /* insert here code to print iCode as comment */
13279           l = Safe_strdup(printILine(ic));
13280           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13281       }
13282         
13283       /* if the result is marked as
13284        * spilt and rematerializable or code for
13285        * this has already been generated then
13286        * do nothing */
13287       if (resultRemat(ic) || ic->generated ) 
13288         continue ;
13289         
13290       /* depending on the operation */
13291       switch (ic->op) {
13292         case '!' :
13293           pic16_genNot(ic);
13294           break;
13295             
13296         case '~' :
13297           pic16_genCpl(ic);
13298           break;
13299             
13300         case UNARYMINUS:
13301           genUminus (ic);
13302           break;
13303             
13304         case IPUSH:
13305           genIpush (ic);
13306           break;
13307             
13308         case IPOP:
13309           /* IPOP happens only when trying to restore a 
13310            * spilt live range, if there is an ifx statement
13311            * following this pop then the if statement might
13312            * be using some of the registers being popped which
13313            * would destroy the contents of the register so
13314            * we need to check for this condition and handle it */
13315            if (ic->next
13316              && ic->next->op == IFX
13317              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13318                genIfx (ic->next,ic);
13319           else
13320             genIpop (ic);
13321           break; 
13322             
13323         case CALL:
13324           genCall (ic);
13325           break;
13326             
13327         case PCALL:
13328           genPcall (ic);
13329           break;
13330             
13331         case FUNCTION:
13332           genFunction (ic);
13333           break;
13334             
13335         case ENDFUNCTION:
13336           genEndFunction (ic);
13337           break;
13338             
13339         case RETURN:
13340           genRet (ic);
13341           break;
13342             
13343         case LABEL:
13344           genLabel (ic);
13345           break;
13346             
13347         case GOTO:
13348           genGoto (ic);
13349           break;
13350             
13351         case '+' :
13352           pic16_genPlus (ic) ;
13353           break;
13354             
13355         case '-' :
13356           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13357             pic16_genMinus (ic);
13358           break;
13359
13360         case '*' :
13361           genMult (ic);
13362           break;
13363             
13364         case '/' :
13365           genDiv (ic) ;
13366           break;
13367             
13368         case '%' :
13369           genMod (ic);
13370           break;
13371             
13372         case '>' :
13373           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13374           break;
13375             
13376         case '<' :
13377           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13378           break;
13379             
13380         case LE_OP:
13381         case GE_OP:
13382         case NE_OP:
13383           /* note these two are xlated by algebraic equivalence
13384            * during parsing SDCC.y */
13385           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13386             "got '>=' or '<=' shouldn't have come here");
13387           break;
13388
13389         case EQ_OP:
13390           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13391           break;            
13392             
13393         case AND_OP:
13394           genAndOp (ic);
13395           break;
13396             
13397         case OR_OP:
13398           genOrOp (ic);
13399           break;
13400             
13401         case '^' :
13402           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13403           break;
13404             
13405         case '|' :
13406           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13407           break;
13408             
13409         case BITWISEAND:
13410           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13411           break;
13412             
13413         case INLINEASM:
13414           genInline (ic);
13415           break;
13416             
13417         case RRC:
13418           genRRC (ic);
13419           break;
13420             
13421         case RLC:
13422           genRLC (ic);
13423           break;
13424             
13425         case GETHBIT:
13426           genGetHbit (ic);
13427           break;
13428             
13429         case LEFT_OP:
13430           genLeftShift (ic);
13431           break;
13432             
13433         case RIGHT_OP:
13434           genRightShift (ic);
13435           break;
13436             
13437         case GET_VALUE_AT_ADDRESS:
13438           genPointerGet(ic);
13439           break;
13440             
13441         case '=' :
13442           if (POINTER_SET(ic))
13443             genPointerSet(ic);
13444           else
13445             genAssign(ic);
13446           break;
13447             
13448         case IFX:
13449           genIfx (ic,NULL);
13450           break;
13451             
13452         case ADDRESS_OF:
13453           genAddrOf (ic);
13454           break;
13455             
13456         case JUMPTABLE:
13457           genJumpTab (ic);
13458           break;
13459             
13460         case CAST:
13461           genCast (ic);
13462           break;
13463             
13464         case RECEIVE:
13465           genReceive(ic);
13466           break;
13467             
13468         case SEND:
13469           addSet(&_G.sendSet,ic);
13470           break;
13471
13472         case DUMMY_READ_VOLATILE:
13473           genDummyRead (ic);
13474           break;
13475
13476         default :
13477           ic = ic;
13478       }
13479     }
13480
13481
13482     /* now we are ready to call the
13483        peep hole optimizer */
13484     if (!options.nopeep)
13485       peepHole (&lineHead);
13486
13487     /* now do the actual printing */
13488     printLine (lineHead, codeOutFile);
13489
13490 #ifdef PCODE_DEBUG
13491     DFPRINTF((stderr,"printing pBlock\n\n"));
13492     pic16_printpBlock(stdout,pb);
13493 #endif
13494
13495     return;
13496 }
13497