* src/pic16/gen.c (genFunction, genEndFunction): also preserve
[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 AT users.sourceforge.net> (2003-2006)
10   Bug Fixes  -  Raphael Neider <rneider AT 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 #include "glue.h"
51
52 /* Set the following to 1 to enable the slower/bigger
53  * but more robust generic shifting routine (which also
54  * operates correctly with negative shift values). */
55 #define USE_GENERIC_SIGNED_SHIFT 1
56
57 /* Set the following to 1 to enable the new
58  * stripped down genCmp version.
59  * This version should be easier to understand,
60  * more reliable and (sigh) slighly slower. */
61 #define USE_SIMPLE_GENCMP 1
62
63 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
64 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
66 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
67 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
68
69 /* If you change these, you also have to update the library files
70  * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
71 #define GPTR_TAG_DATA   0x80
72 #define GPTR_TAG_EEPROM 0x40
73 #define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
74
75 /* Wrapper to execute `code' at most once. */
76 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
77
78 void pic16_genMult8X8_n (operand *, operand *,operand *);
79 #if 0
80 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
81 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
82 void pic16_genMult16X16_16(operand *, operand *, operand *);
83 void pic16_genMult32X32_32(operand *, operand *, operand *);
84 #endif
85 pCode *pic16_AssembleLine(char *line, int peeps);
86 extern void pic16_printpBlock(FILE *of, pBlock *pb);
87 static asmop *newAsmop (short type);
88 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
89 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
90 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
91 static pCodeOp *pic16_popRegFromIdx(int rIdx);
92
93 //static int aopIdx (asmop *aop, int offset);
94
95 int pic16_labelOffset=0;
96 extern int pic16_debug_verbose;
97 #if !(USE_GENERIC_SIGNED_SHIFT)
98 static int optimized_for_speed = 0;
99 #endif
100 /*
101   hack hack
102
103 */
104
105 extern set *externs;
106
107 /* max_key keeps track of the largest label number used in 
108    a function. This is then used to adjust the label offset
109    for the next function.
110 */
111 static int max_key=0;
112 static int GpsuedoStkPtr=0;
113
114 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
115
116 const char *pic16_AopType(short type);
117 static iCode *ifxForOp ( operand *op, iCode *ic );
118
119 void pic16_pushpCodeOp(pCodeOp *pcop);
120 void pic16_poppCodeOp(pCodeOp *pcop);
121
122 static bool is_LitOp(operand *op);
123 static bool is_LitAOp(asmop *aop);
124
125
126 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
127
128 /* set the following macro to 1 to enable passing the
129  * first byte of functions parameters via WREG */
130 #define USE_WREG_IN_FUNC_PARAMS 0
131
132
133 /* this is the down and dirty file with all kinds of 
134    kludgy & hacky stuff. This is what it is all about
135    CODE GENERATION for a specific MCU . some of the
136    routines may be reusable, will have to see */
137
138 static char *zero = "#0x00";
139 static char *one  = "#0x01";
140 //static char *spname = "sp";
141
142
143 /*
144  * Function return value policy (MSB-->LSB):
145  *  8 bits      -> WREG
146  * 16 bits      -> PRODL:WREG
147  * 24 bits      -> PRODH:PRODL:WREG
148  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
149  * >32 bits     -> on stack, and FSR0 points to the beginning
150  *
151  */
152  
153
154 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
155 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
156 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
157 static char **fReturn = fReturnpic16;
158
159 static char *accUse[] = {"WREG"};
160
161 //static short rbank = -1;
162
163 static struct {
164     short r0Pushed;
165     short r1Pushed;
166     short fsr0Pushed;
167     short accInUse;
168     short inLine;
169     short debugLine;
170     short nRegsSaved;
171     short ipushRegs;
172     set *sendSet;
173     set *stackRegSet;
174     int usefastretfie;
175     bitVect *fregsUsed;                 /* registers used in function */
176     bitVect *sregsAlloc;
177     set *sregsAllocSet;                 /* registers used to store stack variables */
178     int stack_lat;                      /* stack offset latency */
179     int resDirect;
180     int useWreg;                        /* flag when WREG is used to pass function parameter */
181 } _G;
182
183 extern int pic16_ptrRegReq ;
184 extern int pic16_nRegs;
185 extern FILE *codeOutFile;
186 //static void saverbank (int, iCode *,bool);
187
188 static lineNode *lineHead = NULL;
189 static lineNode *lineCurr = NULL;
190
191 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
192 0xE0, 0xC0, 0x80, 0x00};
193 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
194 0x07, 0x03, 0x01, 0x00};
195
196 static  pBlock *pb;
197
198 /*-----------------------------------------------------------------*/
199 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
200 /*                 exponent of 2 is returned, otherwise -1 is      */
201 /*                 returned.                                       */
202 /* note that this is similar to the function `powof2' in SDCCsymt  */
203 /* if(n == 2^y)                                                    */
204 /*   return y;                                                     */
205 /* return -1;                                                      */
206 /*-----------------------------------------------------------------*/
207 int pic16_my_powof2 (unsigned long num)
208 {
209   if(num) {
210     if( (num & (num-1)) == 0) {
211       int nshifts = -1;
212       while(num) {
213         num>>=1;
214         nshifts++;
215       }
216       return nshifts;
217     }
218   }
219
220   return -1;
221 }
222
223 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
224 {
225   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
226                        line_no,
227                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
228                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
229                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
230                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
231                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
232                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
233                        ((result) ? AOP_SIZE(result) : 0));
234 }
235
236 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
237 {
238
239   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
240                        line_no,
241                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
242                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
243                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
244                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
245                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
246                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
247
248 }
249
250 void pic16_emitpcomment (char *fmt, ...)
251 {
252     va_list ap;
253     char lb[INITIAL_INLINEASM];  
254     unsigned char *lbp = (unsigned char *)lb;
255
256     va_start(ap,fmt);   
257
258     lb[0] = ';';
259     vsprintf(lb+1,fmt,ap);
260
261     while (isspace(*lbp)) lbp++;
262
263     if (lbp && *lbp) 
264         lineCurr = (lineCurr ?
265                     connectLine(lineCurr,newLineNode(lb)) :
266                     (lineHead = newLineNode(lb)));
267     lineCurr->isInline = _G.inLine;
268     lineCurr->isDebug  = _G.debugLine;
269
270     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
271     va_end(ap);
272
273 //      fprintf(stderr, "%s\n", lb);
274 }
275
276 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
277 {
278     va_list ap;
279     char lb[INITIAL_INLINEASM];  
280     unsigned char *lbp = (unsigned char *)lb;
281
282     if(!pic16_debug_verbose)
283       return;
284
285     va_start(ap,fmt);   
286
287     if (inst && *inst) {
288         if (fmt && *fmt)
289             sprintf(lb,"%s\t",inst);
290         else
291             sprintf(lb,"%s",inst);
292         vsprintf(lb+(strlen(lb)),fmt,ap);
293     }  else
294         vsprintf(lb,fmt,ap);
295
296     while (isspace(*lbp)) lbp++;
297
298     if (lbp && *lbp) 
299         lineCurr = (lineCurr ?
300                     connectLine(lineCurr,newLineNode(lb)) :
301                     (lineHead = newLineNode(lb)));
302     lineCurr->isInline = _G.inLine;
303     lineCurr->isDebug  = _G.debugLine;
304
305     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
306     va_end(ap);
307
308 //      fprintf(stderr, "%s\n", lb);
309 }
310
311
312
313 void pic16_emitpLabel(int key)
314 {
315   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
316 }
317
318 void pic16_emitpLabelFORCE(int key)
319 {
320   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
321 }
322
323 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
324  * NEVER call pic16_emitpcode_real directly, please... */
325 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
326 {
327
328   if(pcop)
329     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
330   else
331     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
332 }
333
334 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
335 {
336   if(pcop)
337     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
338   else
339     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
340 }
341   
342 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
343 {
344
345   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
346
347 }
348
349
350 #if 1
351 #define pic16_emitcode  DEBUGpic16_emitcode
352 #else
353 /*-----------------------------------------------------------------*/
354 /* pic16_emitcode - writes the code into a file : for now it is simple    */
355 /*-----------------------------------------------------------------*/
356 void pic16_emitcode (char *inst,char *fmt, ...)
357 {
358     va_list ap;
359     char lb[INITIAL_INLINEASM];  
360     unsigned char *lbp = lb;
361
362     va_start(ap,fmt);   
363
364     if (inst && *inst) {
365         if (fmt && *fmt)
366             sprintf(lb,"%s\t",inst);
367         else
368             sprintf(lb,"%s",inst);
369         vsprintf(lb+(strlen(lb)),fmt,ap);
370     }  else
371         vsprintf(lb,fmt,ap);
372
373     while (isspace(*lbp)) lbp++;
374
375     if (lbp && *lbp) 
376         lineCurr = (lineCurr ?
377                     connectLine(lineCurr,newLineNode(lb)) :
378                     (lineHead = newLineNode(lb)));
379     lineCurr->isInline = _G.inLine;
380     lineCurr->isDebug  = _G.debugLine;
381
382 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
383
384 //    if(pic16_debug_verbose)
385 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
386
387     va_end(ap);
388 }
389 #endif
390
391
392 /*-----------------------------------------------------------------*/
393 /* pic16_emitDebuggerSymbol - associate the current code location  */
394 /*   with a debugger symbol                                        */
395 /*-----------------------------------------------------------------*/
396 void
397 pic16_emitDebuggerSymbol (char * debugSym)
398 {
399   _G.debugLine = 1;
400   pic16_emitcode (";", "%s ==.", debugSym);
401   _G.debugLine = 0;
402 }
403
404
405 /*-----------------------------------------------------------------*/
406 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
407 /*-----------------------------------------------------------------*/
408 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
409 {
410 //    bool r0iu = FALSE , r1iu = FALSE;
411 //    bool r0ou = FALSE , r1ou = FALSE;
412     bool fsr0iu = FALSE, fsr0ou;
413     bool fsr2iu = FALSE, fsr2ou;
414     
415     //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__,  __FUNCTION__, __LINE__, ic->op, result);
416
417     
418     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
419     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
420     
421     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
422     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
423
424     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
425         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
426         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
427     }
428
429     if(!fsr0iu && !fsr0ou) {
430         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
431         (*aopp)->type = AOP_FSR0;
432
433         //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
434         
435       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
436     }
437
438 #if 0
439     /* no usage of FSR2 */
440     if(!fsr2iu && !fsr2ou) {
441         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
442         (*aopp)->type = AOP_FSR2;
443
444       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
445     }
446 #endif
447         
448     /* now we know they both have usage */
449     /* if fsr0 not used in this instruction */
450     if (!fsr0iu) {
451         if (!_G.fsr0Pushed) {
452                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
453                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
454                 _G.fsr0Pushed++;
455         }
456
457         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
458         (*aopp)->type = AOP_FSR0;
459
460 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
461
462       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
463     }
464         
465
466     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
467     assert( 0 );
468
469     return NULL;
470 #if 0
471     /* the logic: if r0 & r1 used in the instruction
472     then we are in trouble otherwise */
473
474     /* first check if r0 & r1 are used by this
475     instruction, in which case we are in trouble */
476     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
477         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
478     {
479         goto endOfWorld;      
480     }
481
482     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
483     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
484
485     /* if no usage of r0 then return it */
486     if (!r0iu && !r0ou) {
487         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
488         (*aopp)->type = AOP_R0; 
489         
490         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
491     }
492
493     /* if no usage of r1 then return it */
494     if (!r1iu && !r1ou) {
495         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
496         (*aopp)->type = AOP_R1;
497
498         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
499     }    
500
501     /* now we know they both have usage */
502     /* if r0 not used in this instruction */
503     if (!r0iu) {
504         /* push it if not already pushed */
505         if (!_G.r0Pushed) {
506           //pic16_emitcode ("push","%s",
507           //          pic16_regWithIdx(R0_IDX)->dname);
508             _G.r0Pushed++ ;
509         }
510         
511         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
512         (*aopp)->type = AOP_R0;
513
514         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
515     }
516
517     /* if r1 not used then */
518
519     if (!r1iu) {
520         /* push it if not already pushed */
521         if (!_G.r1Pushed) {
522           //pic16_emitcode ("push","%s",
523           //          pic16_regWithIdx(R1_IDX)->dname);
524             _G.r1Pushed++ ;
525         }
526         
527         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
528         (*aopp)->type = AOP_R1;
529         return pic16_regWithIdx(R1_IDX);
530     }
531
532 endOfWorld :
533     /* I said end of world but not quite end of world yet */
534     /* if this is a result then we can push it on the stack*/
535     if (result) {
536         (*aopp)->type = AOP_STK;    
537         return NULL;
538     }
539
540     /* other wise this is true end of the world */
541     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
542            "getFreePtr should never reach here");
543     exit(0);
544 #endif
545 }
546
547 /*-----------------------------------------------------------------*/
548 /* newAsmop - creates a new asmOp                                  */
549 /*-----------------------------------------------------------------*/
550 static asmop *newAsmop (short type)
551 {
552     asmop *aop;
553
554     aop = Safe_calloc(1,sizeof(asmop));
555     aop->type = type;
556     return aop;
557 }
558
559 static void genSetDPTR(int n)
560 {
561     if (!n)
562     {
563         pic16_emitcode(";", "Select standard DPTR");
564         pic16_emitcode("mov", "dps, #0x00");
565     }
566     else
567     {
568         pic16_emitcode(";", "Select alternate DPTR");
569         pic16_emitcode("mov", "dps, #0x01");
570     }
571 }
572
573 /*-----------------------------------------------------------------*/
574 /* resolveIfx - converts an iCode ifx into a form more useful for  */
575 /*              generating code                                    */
576 /*-----------------------------------------------------------------*/
577 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
578 {
579   FENTRY2;
580   
581 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
582
583   if(!resIfx) 
584     return;
585
586
587   resIfx->condition = 1;    /* assume that the ifx is true */
588   resIfx->generated = 0;    /* indicate that the ifx has not been used */
589
590   if(!ifx) {
591     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
592
593 #if 1
594     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
595                         __FUNCTION__,__LINE__,resIfx->lbl->key);
596 #endif
597
598   } else {
599     if(IC_TRUE(ifx)) {
600       resIfx->lbl = IC_TRUE(ifx);
601     } else {
602       resIfx->lbl = IC_FALSE(ifx);
603       resIfx->condition = 0;
604     }
605
606 #if 1
607     if(IC_TRUE(ifx)) 
608       DEBUGpic16_emitcode("; +++","ifx true is non-null");
609     else
610       DEBUGpic16_emitcode("; +++","ifx true is null");
611     if(IC_FALSE(ifx)) 
612       DEBUGpic16_emitcode("; +++","ifx false is non-null");
613     else
614       DEBUGpic16_emitcode("; +++","ifx false is null");
615 #endif
616   }
617
618   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
619
620 }
621 #if 0
622 /*-----------------------------------------------------------------*/
623 /* pointerCode - returns the code for a pointer type               */
624 /*-----------------------------------------------------------------*/
625 static int pointerCode (sym_link *etype)
626 {
627
628     return PTR_TYPE(SPEC_OCLS(etype));
629
630 }
631 #endif
632
633 /*-----------------------------------------------------------------*/
634 /* aopForSym - for a true symbol                                   */
635 /*-----------------------------------------------------------------*/
636 static asmop *aopForSym (iCode *ic, operand *op, bool result)
637 {
638     symbol *sym=OP_SYMBOL(op);
639     asmop *aop;
640     memmap *space= SPEC_OCLS(sym->etype);
641
642     FENTRY2;
643     
644     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
645     
646 //    sym = OP_SYMBOL(op);
647
648     /* if already has one */
649     if (sym->aop) {
650             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
651         return sym->aop;
652     }
653
654 #if 0
655     /* if symbol was initially placed onStack then we must re-place it
656      * to direct memory, since pic16 does not have a specific stack */
657     if(sym->onStack) {
658         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
659     }
660 #endif
661
662
663 #if 0
664     if(sym->iaccess) {
665       if(space->paged) {
666         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
667
668         sym->aop = aop = newAsmop (AOP_PAGED);
669         aop->aopu.aop_dir = sym->rname ;
670         aop->size = getSize(sym->type);
671         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
672         pic16_allocDirReg( IC_LEFT(ic) );
673         return aop;
674       }
675       assert( 0 );
676     }
677 #endif
678     
679 #if 1
680     /* assign depending on the storage class */
681     /* if it is on the stack or indirectly addressable */
682     /* space we need to assign either r0 or r1 to it   */    
683     if (sym->onStack)   // || sym->iaccess)
684     {
685       pCodeOp *pcop[4];
686       int i;
687       
688         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
689                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
690         
691         /* acquire a temporary register -- it is saved in function */
692
693         sym->aop = aop = newAsmop(AOP_STA);
694         aop->aopu.stk.stk = sym->stack;
695         aop->size = getSize(sym->type);
696
697
698         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
699         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
700           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
701 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
702           
703           for(i=0;i<aop->size;i++)
704             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
705             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
706         } else
707         if(1 && ic->op == SEND) {
708
709           /* if SEND do the send here */
710           _G.resDirect = 1;
711         } else {
712 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
713           for(i=0;i<aop->size;i++) {
714             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
715             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
716           }
717         }
718
719
720 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
721
722 #if 1
723         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
724
725         // we do not need to load the value if it is to be defined...
726         if (result) return aop;
727
728         if(_G.accInUse) {
729                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
730         }
731         
732         for(i=0;i<aop->size;i++) {
733
734           /* initialise for stack access via frame pointer */
735           // operands on stack are accessible via "{FRAME POINTER} + index" with index
736           // starting at 2 for arguments and growing from 0 downwards for
737           // local variables (index == 0 is not assigned so we add one here)
738           {
739             int soffs = sym->stack;
740             if (soffs <= 0) {
741               assert (soffs < 0);
742               soffs++;
743             } // if
744
745             if(1 && ic->op == SEND) {
746               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
747               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
748                     pic16_popCopyReg( pic16_frame_plusw ),
749                     pic16_popCopyReg(pic16_stack_postdec )));
750             } else {
751               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
752               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
753                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
754             }
755           }
756         }
757         
758         if(_G.accInUse) {
759                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
760         }
761         
762         return (aop);
763 #endif
764
765 #if 0
766         /* now assign the address of the variable to 
767         the pointer register */
768         if (aop->type != AOP_STK) {
769
770             if (sym->onStack) {
771                     if ( _G.accInUse )
772                         pic16_emitcode("push","acc");
773
774                     pic16_emitcode("mov","a,_bp");
775                     pic16_emitcode("add","a,#0x%02x",
776                              ((sym->stack < 0) ?
777                               ((char)(sym->stack - _G.nRegsSaved )) :
778                               ((char)sym->stack)) & 0xff);
779                     pic16_emitcode("mov","%s,a",
780                              aop->aopu.aop_ptr->name);
781
782                     if ( _G.accInUse )
783                         pic16_emitcode("pop","acc");
784             } else
785                 pic16_emitcode("mov","%s,#%s",
786                          aop->aopu.aop_ptr->name,
787                          sym->rname);
788             aop->paged = space->paged;
789         } else
790             aop->aopu.aop_stk = sym->stack;
791         return aop;
792 #endif
793
794     }
795 #endif
796
797 #if 0
798     if (sym->onStack && options.stack10bit)
799     {
800         /* It's on the 10 bit stack, which is located in
801          * far data space.
802          */
803          
804       //DEBUGpic16_emitcode(";","%d",__LINE__);
805
806         if ( _G.accInUse )
807                 pic16_emitcode("push","acc");
808
809         pic16_emitcode("mov","a,_bp");
810         pic16_emitcode("add","a,#0x%02x",
811                  ((sym->stack < 0) ?
812                    ((char)(sym->stack - _G.nRegsSaved )) :
813                    ((char)sym->stack)) & 0xff);
814         
815         genSetDPTR(1);
816         pic16_emitcode ("mov","dpx1,#0x40");
817         pic16_emitcode ("mov","dph1,#0x00");
818         pic16_emitcode ("mov","dpl1, a");
819         genSetDPTR(0);
820         
821         if ( _G.accInUse )
822             pic16_emitcode("pop","acc");
823             
824         sym->aop = aop = newAsmop(AOP_DPTR2);
825         aop->size = getSize(sym->type); 
826         return aop;
827     }
828 #endif
829
830 #if 1
831     /* special case for a function */
832     if (IS_FUNC(sym->type)) {   
833         sym->aop = aop = newAsmop(AOP_PCODE);
834         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
835         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
836         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
837         PCOI(aop->aopu.pcop)->index = 0;
838         aop->size = FPTRSIZE; 
839         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
840         return aop;
841     }
842 #endif
843
844
845
846     //DEBUGpic16_emitcode(";","%d",__LINE__);
847     /* if in bit space */
848     if (IN_BITSPACE(space)) {
849         sym->aop = aop = newAsmop (AOP_CRY);
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         return aop;
854     }
855     /* if it is in direct space */
856     if (IN_DIRSPACE(space)) {
857                 if(!strcmp(sym->rname, "_WREG")) {
858                         sym->aop = aop = newAsmop (AOP_ACC);
859                         aop->size = getSize(sym->type);         /* should always be 1 */
860                         assert(aop->size == 1);
861                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
862                         return (aop);
863                 } else {
864                         sym->aop = aop = newAsmop (AOP_DIR);
865                 aop->aopu.aop_dir = sym->rname ;
866             aop->size = getSize(sym->type);
867                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
868                         pic16_allocDirReg( IC_LEFT(ic) );
869                         return (aop);
870                 }
871         }
872
873     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
874         sym->aop = aop = newAsmop (AOP_DIR);
875         aop->aopu.aop_dir = sym->rname ;
876         aop->size = getSize(sym->type);
877         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
878         pic16_allocDirReg( IC_LEFT(ic) );
879         return aop;
880     }
881
882
883     /* only remaining is far space */
884     sym->aop = aop = newAsmop(AOP_PCODE);
885
886 /* change the next if to 1 to revert to good old immediate code */
887         if(IN_CODESPACE(space)) {
888                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
889                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
890                 PCOI(aop->aopu.pcop)->index = 0;
891         } else {
892                 /* try to allocate via direct register */
893                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
894 //              aop->size = getSize( sym->type );
895         }
896
897         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
898                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
899
900 #if 0
901         if(!pic16_allocDirReg (IC_LEFT(ic)))
902                 return NULL;
903 #endif
904
905         if(IN_DIRSPACE( space ))
906                 aop->size = PTRSIZE;
907         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
908                 aop->size = FPTRSIZE;
909         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
910         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
911         else if(sym->onStack) {
912                 aop->size = PTRSIZE;
913         } else {
914           if(SPEC_SCLS(sym->etype) == S_PDATA) {
915             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
916             aop->size = FPTRSIZE;
917           } else
918                 assert( 0 );
919         }
920
921     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
922
923     /* if it is in code space */
924     if (IN_CODESPACE(space))
925         aop->code = 1;
926
927     return aop;     
928 }
929
930 /*-----------------------------------------------------------------*/
931 /* aopForRemat - rematerialzes an object                           */
932 /*-----------------------------------------------------------------*/
933 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
934 {
935   symbol *sym = OP_SYMBOL(op);
936   operand *refop;
937   iCode *ic = NULL, *oldic;
938   asmop *aop = newAsmop(AOP_PCODE);
939   int val = 0;
940   int offset = 0;
941   int viaimmd=0;
942
943     FENTRY2;
944     
945         ic = sym->rematiCode;
946
947         if(IS_OP_POINTER(op)) {
948                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
949         }
950
951 //    if(!result)               /* fixme-vr */
952         for (;;) {
953                 oldic = ic;
954
955 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
956         
957                 if (ic->op == '+') {
958                         val += (int) operandLitValue(IC_RIGHT(ic));
959                 } else if (ic->op == '-') {
960                         val -= (int) operandLitValue(IC_RIGHT(ic));
961                 } else
962                         break;
963                 
964                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
965         }
966
967         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
968         refop = IC_LEFT(ic);
969
970         if(!op->isaddr)viaimmd++; else viaimmd=0;
971                 
972 /* set the following if to 1 to revert to good old immediate code */
973         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
974                 || viaimmd) {
975
976                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
977
978                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
979
980 #if 0
981                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
982 #else
983                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
984 #endif
985
986                 PCOI(aop->aopu.pcop)->index = val;
987                 
988                 aop->size = getSize( sym->type );
989         } else {
990                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
991
992                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
993                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
994
995                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
996         }
997
998
999         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1000                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1001 #if 0
1002                 val, IS_PTR_CONST(operandType(op)));
1003 #else
1004                 val, IS_CODEPTR(operandType(op)));
1005 #endif
1006
1007 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1008
1009         pic16_allocDirReg (IC_LEFT(ic));
1010
1011         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1012                 aop->code = 1;
1013
1014   return aop;        
1015 }
1016
1017 #if 0
1018 static int aopIdx (asmop *aop, int offset)
1019 {
1020   if(!aop)
1021     return -1;
1022
1023   if(aop->type !=  AOP_REG)
1024     return -2;
1025         
1026   return aop->aopu.aop_reg[offset]->rIdx;
1027
1028 }
1029 #endif
1030
1031 /*-----------------------------------------------------------------*/
1032 /* regsInCommon - two operands have some registers in common       */
1033 /*-----------------------------------------------------------------*/
1034 static bool regsInCommon (operand *op1, operand *op2)
1035 {
1036     symbol *sym1, *sym2;
1037     int i;
1038
1039     /* if they have registers in common */
1040     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1041         return FALSE ;
1042
1043     sym1 = OP_SYMBOL(op1);
1044     sym2 = OP_SYMBOL(op2);
1045
1046     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1047         return FALSE ;
1048
1049     for (i = 0 ; i < sym1->nRegs ; i++) {
1050         int j;
1051         if (!sym1->regs[i])
1052             continue ;
1053
1054         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1055             if (!sym2->regs[j])
1056                 continue ;
1057
1058             if (sym2->regs[j] == sym1->regs[i])
1059                 return TRUE ;
1060         }
1061     }
1062
1063     return FALSE ;
1064 }
1065
1066 /*-----------------------------------------------------------------*/
1067 /* operandsEqu - equivalent                                        */
1068 /*-----------------------------------------------------------------*/
1069 static bool operandsEqu ( operand *op1, operand *op2)
1070 {
1071     symbol *sym1, *sym2;
1072
1073     /* if they not symbols */
1074     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1075         return FALSE;
1076
1077     sym1 = OP_SYMBOL(op1);
1078     sym2 = OP_SYMBOL(op2);
1079
1080     /* if both are itemps & one is spilt
1081        and the other is not then false */
1082     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1083         sym1->isspilt != sym2->isspilt )
1084         return FALSE ;
1085
1086     /* if they are the same */
1087     if (sym1 == sym2)
1088         return TRUE ;
1089
1090     if (sym1->rname[0] && sym2->rname[0]
1091         && strcmp (sym1->rname, sym2->rname) == 0)
1092         return TRUE;
1093
1094
1095     /* if left is a tmp & right is not */
1096     if (IS_ITEMP(op1)  && 
1097         !IS_ITEMP(op2) &&
1098         sym1->isspilt  &&
1099         (sym1->usl.spillLoc == sym2))
1100         return TRUE;
1101
1102     if (IS_ITEMP(op2)  && 
1103         !IS_ITEMP(op1) &&
1104         sym2->isspilt  &&
1105         sym1->level > 0 &&
1106         (sym2->usl.spillLoc == sym1))
1107         return TRUE ;
1108
1109     return FALSE ;
1110 }
1111
1112 /*-----------------------------------------------------------------*/
1113 /* pic16_sameRegs - two asmops have the same registers                   */
1114 /*-----------------------------------------------------------------*/
1115 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1116 {
1117     int i;
1118
1119     if (aop1 == aop2)
1120         return TRUE ;
1121
1122     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1123                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1124
1125     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1126
1127     if (aop1->type != AOP_REG ||
1128         aop2->type != AOP_REG )
1129         return FALSE ;
1130
1131     /* This is a bit too restrictive if one is a subset of the other...
1132     if (aop1->size != aop2->size )
1133         return FALSE ;
1134     */
1135
1136     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1137 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1138
1139 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1140         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1141             return FALSE ;
1142     }
1143
1144     return TRUE ;
1145 }
1146
1147 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1148 {
1149     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1150                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1151
1152     if(aop1 == aop2)return TRUE;
1153     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1154       
1155       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1156     
1157   return TRUE;
1158 }
1159
1160
1161 /*-----------------------------------------------------------------*/
1162 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1163 /*-----------------------------------------------------------------*/
1164 void pic16_aopOp (operand *op, iCode *ic, bool result)
1165 {
1166     asmop *aop;
1167     symbol *sym;
1168     int i;
1169
1170     if (!op)
1171         return ;
1172
1173     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1174
1175     /* if this a literal */
1176     if (IS_OP_LITERAL(op)) {
1177         op->aop = aop = newAsmop(AOP_LIT);
1178         aop->aopu.aop_lit = op->operand.valOperand;
1179         aop->size = getSize(operandType(op));
1180         return;
1181     }
1182
1183     {
1184       sym_link *type = operandType(op);
1185 #if 0
1186       if(IS_PTR_CONST(type))
1187 #else
1188       if(IS_CODEPTR(type))
1189 #endif
1190         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1191     }
1192
1193     /* if already has a asmop then continue */
1194     if (op->aop)
1195         return ;
1196
1197     /* if the underlying symbol has a aop */
1198     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1199       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1200         op->aop = OP_SYMBOL(op)->aop;
1201         return;
1202     }
1203
1204     /* if this is a true symbol */
1205     if (IS_TRUE_SYMOP(op)) {    
1206         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1207       op->aop = aopForSym(ic, op, result);
1208       return ;
1209     }
1210
1211     /* this is a temporary : this has
1212     only four choices :
1213     a) register
1214     b) spillocation
1215     c) rematerialize 
1216     d) conditional   
1217     e) can be a return use only */
1218
1219     sym = OP_SYMBOL(op);
1220
1221     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1222     /* if the type is a conditional */
1223     if (sym->regType == REG_CND) {
1224         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1225         aop->size = 0;
1226         return;
1227     }
1228
1229     /* if it is spilt then two situations
1230     a) is rematerialize 
1231     b) has a spill location */
1232     if (sym->isspilt || sym->nRegs == 0) {
1233
1234 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1235       DEBUGpic16_emitcode(";","%d",__LINE__);
1236         /* rematerialize it NOW */
1237         if (sym->remat) {
1238
1239             sym->aop = op->aop = aop = aopForRemat (op, result);
1240 //            aop->size = getSize(sym->type);
1241 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1242             return;
1243         }
1244
1245 #if 1
1246         if (sym->accuse) {
1247             int i;
1248             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1249             aop->size = getSize(sym->type);
1250             for ( i = 0 ; i < 1 ; i++ ) {
1251                 aop->aopu.aop_str[i] = accUse[i];
1252 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1253             }
1254             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1255             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1256             return;  
1257         }
1258 #endif
1259
1260 #if 1
1261         if (sym->ruonly) {
1262           /*
1263           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1264           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1265           //pic16_allocDirReg (IC_LEFT(ic));
1266           aop->size = getSize(sym->type);
1267           */
1268
1269           unsigned i;
1270
1271           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1272           aop->size = getSize(sym->type);
1273           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1274             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1275
1276           DEBUGpic16_emitcode(";","%d",__LINE__);
1277           return;
1278         }
1279 #endif
1280         /* else spill location  */
1281         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1282             /* force a new aop if sizes differ */
1283             sym->usl.spillLoc->aop = NULL;
1284         }
1285
1286 #if 0
1287         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1288                             __FUNCTION__,__LINE__,
1289                             sym->usl.spillLoc->rname,
1290                             sym->rname, sym->usl.spillLoc->offset);
1291 #endif
1292
1293         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1294         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1295           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1296           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1297                                                   getSize(sym->type), 
1298                                                   sym->usl.spillLoc->offset, op);
1299         } else if (getSize(sym->type) <= 1) {
1300           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1301           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1302           assert (getSize(sym->type) <= 1);
1303           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1304           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1305         } else {
1306           /* We need some kind of dummy area for getSize(sym->type) byte,
1307            * use WREG for all storage locations.
1308            * XXX: This only works if we are implementing a `dummy read',
1309            *      the stored value will not be retrievable...
1310            *      See #1503234 for a case requiring this. */
1311           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1312           aop->size = getSize(sym->type);
1313           for ( i = 0 ; i < aop->size ;i++)
1314             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1315         }
1316         aop->size = getSize(sym->type);
1317
1318         return;
1319     }
1320
1321     {
1322       sym_link *type = operandType(op);
1323 #if 0
1324       if(IS_PTR_CONST(type)) 
1325 #else
1326       if(IS_CODEPTR(type)) 
1327 #endif
1328         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1329     }
1330
1331     /* must be in a register */
1332     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1333     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1334     aop->size = sym->nRegs;
1335     for ( i = 0 ; i < sym->nRegs ;i++)
1336         aop->aopu.aop_reg[i] = sym->regs[i];
1337 }
1338
1339 /*-----------------------------------------------------------------*/
1340 /* pic16_freeAsmop - free up the asmop given to an operand               */
1341 /*----------------------------------------------------------------*/
1342 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1343 {   
1344     asmop *aop ;
1345
1346     if (!op)
1347         aop = aaop;
1348     else 
1349         aop = op->aop;
1350
1351     if (!aop)
1352         return ;
1353
1354     if (aop->freed)
1355         goto dealloc; 
1356
1357     aop->freed = 1;
1358
1359     /* depending on the asmop type only three cases need work AOP_RO
1360        , AOP_R1 && AOP_STK */
1361 #if 1
1362     switch (aop->type) {
1363         case AOP_FSR0 :
1364             if (_G.fsr0Pushed ) {
1365                 if (pop) {
1366                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1367                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1368 //                    pic16_emitcode ("pop","ar0");
1369                     _G.fsr0Pushed--;
1370                 }
1371             }
1372             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1373             break;
1374
1375         case AOP_FSR2 :
1376             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1377             break;
1378
1379         case AOP_R0 :
1380             if (_G.r0Pushed ) {
1381                 if (pop) {
1382                     pic16_emitcode ("pop","ar0");     
1383                     _G.r0Pushed--;
1384                 }
1385             }
1386             bitVectUnSetBit(ic->rUsed,R0_IDX);
1387             break;
1388
1389         case AOP_R1 :
1390             if (_G.r1Pushed ) {
1391                 if (pop) {
1392                     pic16_emitcode ("pop","ar1");
1393                     _G.r1Pushed--;
1394                 }
1395             }
1396             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1397             break;
1398
1399         case AOP_STA:
1400           {
1401             int i;
1402
1403               /* we must store the result on stack */
1404               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1405                 // operands on stack are accessible via "FSR2 + index" with index
1406                 // starting at 2 for arguments and growing from 0 downwards for
1407                 // local variables (index == 0 is not assigned so we add one here)
1408                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1409                 if (soffs <= 0) {
1410                   assert (soffs < 0);
1411                   soffs++;
1412                 } // if
1413                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1414                 for(i=0;i<aop->size;i++) {
1415                   /* initialise for stack access via frame pointer */
1416                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1417                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1418                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1419                 }
1420         
1421                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1422               }
1423
1424               if(!_G.resDirect) {
1425                 for(i=0;i<aop->size;i++) {
1426                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1427
1428                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1429                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1430 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1431                   }
1432                 }
1433                 
1434                 {
1435                   regs *sr;
1436                   
1437                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1438                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1439                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1440                       deleteSetItem( &_G.sregsAllocSet, sr );
1441                     }
1442                 }
1443               }
1444               _G.resDirect = 0;
1445           }
1446           break;
1447 #if 0
1448         case AOP_STK :
1449         {
1450             int sz = aop->size;    
1451             int stk = aop->aopu.aop_stk + aop->size;
1452             bitVectUnSetBit(ic->rUsed,R0_IDX);
1453             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1454
1455             getFreePtr(ic,&aop,FALSE);
1456             
1457             if (options.stack10bit)
1458             {
1459                 /* I'm not sure what to do here yet... */
1460                 /* #STUB */
1461                 fprintf(stderr, 
1462                         "*** Warning: probably generating bad code for "
1463                         "10 bit stack mode.\n");
1464             }
1465             
1466             if (stk) {
1467                 pic16_emitcode ("mov","a,_bp");
1468                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1469                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1470             } else {
1471                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1472             }
1473
1474             while (sz--) {
1475                 pic16_emitcode("pop","acc");
1476                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1477                 if (!sz) break;
1478                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1479             }
1480             op->aop = aop;
1481             pic16_freeAsmop(op,NULL,ic,TRUE);
1482             if (_G.r0Pushed) {
1483                 pic16_emitcode("pop","ar0");
1484                 _G.r0Pushed--;
1485             }
1486
1487             if (_G.r1Pushed) {
1488                 pic16_emitcode("pop","ar1");
1489                 _G.r1Pushed--;
1490             }       
1491         }
1492 #endif
1493
1494     }
1495 #endif
1496
1497 dealloc:
1498     /* all other cases just dealloc */
1499     if (op ) {
1500         op->aop = NULL;
1501         if (IS_SYMOP(op)) {
1502             OP_SYMBOL(op)->aop = NULL;    
1503             /* if the symbol has a spill */
1504             if (SPIL_LOC(op))
1505                 SPIL_LOC(op)->aop = NULL;
1506         }
1507     }
1508 }
1509
1510 /*-----------------------------------------------------------------*/
1511 /* pic16_aopGet - for fetching value of the aop                          */
1512 /*-----------------------------------------------------------------*/
1513 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1514 {
1515     char *s = buffer ;
1516     char *rs;
1517
1518     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1519
1520     /* offset is greater than size then zero */
1521     if (offset > (aop->size - 1) &&
1522         aop->type != AOP_LIT)
1523         return zero;
1524
1525     /* depending on type */
1526     switch (aop->type) {
1527
1528     case AOP_FSR0:
1529     case AOP_FSR2:
1530       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1531       rs = Safe_calloc(1, strlen(s)+1);
1532       strcpy(rs, s);
1533       return (rs);
1534       
1535 #if 0
1536       /* if we need to increment it */
1537       while (offset > aop->coff)
1538         {
1539           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1540           aop->coff++;
1541         }
1542
1543       while (offset < aop->coff)
1544         {
1545           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1546           aop->coff--;
1547         }
1548       aop->coff = offset;
1549       if (aop->paged)
1550         {
1551           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1552           return (dname ? "acc" : "a");
1553         }
1554       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1555       rs = Safe_calloc (1, strlen (s) + 1);
1556       strcpy (rs, s);
1557       return rs;
1558 #endif
1559
1560         
1561     case AOP_IMMD:
1562         if (bit16) 
1563             sprintf (s,"%s",aop->aopu.aop_immd);
1564         else
1565             if (offset) 
1566                 sprintf(s,"(%s >> %d)",
1567                         aop->aopu.aop_immd,
1568                         offset*8);
1569             else
1570                 sprintf(s,"%s",
1571                         aop->aopu.aop_immd);
1572         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1573         rs = Safe_calloc(1,strlen(s)+1);
1574         strcpy(rs,s);   
1575         return rs;
1576         
1577     case AOP_DIR:
1578       if (offset) {
1579         sprintf(s,"(%s + %d)",
1580                 aop->aopu.aop_dir,
1581                 offset);
1582         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1583       } else
1584             sprintf(s,"%s",aop->aopu.aop_dir);
1585         rs = Safe_calloc(1,strlen(s)+1);
1586         strcpy(rs,s);   
1587         return rs;
1588         
1589     case AOP_REG:
1590       return aop->aopu.aop_reg[offset]->name;
1591         
1592     case AOP_CRY:
1593       return aop->aopu.aop_dir;
1594         
1595     case AOP_ACC:
1596         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1597 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1598 //        assert( 0 );
1599 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1600         rs = Safe_strdup("WREG");
1601         return (rs);
1602
1603     case AOP_LIT:
1604         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1605         rs = Safe_calloc(1,strlen(s)+1);
1606         strcpy(rs,s);   
1607         return rs;
1608         
1609     case AOP_STR:
1610         aop->coff = offset ;
1611
1612 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1613 //          dname)
1614 //          return "acc";
1615         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1616           aop->type = AOP_ACC;
1617           return Safe_strdup("_WREG");
1618         }
1619         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1620         
1621         return aop->aopu.aop_str[offset];
1622         
1623     case AOP_PCODE:
1624       {
1625         pCodeOp *pcop = aop->aopu.pcop;
1626         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1627         if(pcop->name) {
1628           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1629           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1630           if (offset) {
1631             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1632           } else {
1633             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1634           }
1635         } else
1636           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1637
1638       }
1639       rs = Safe_calloc(1,strlen(s)+1);
1640       strcpy(rs,s);   
1641       return rs;
1642
1643 #if 0
1644     case AOP_PAGED:
1645       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1646       if (offset) {
1647         sprintf(s,"(%s + %d)",
1648                 aop->aopu.aop_dir,
1649                 offset);
1650       } else
1651             sprintf(s,"%s",aop->aopu.aop_dir);
1652       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1653       rs = Safe_calloc(1,strlen(s)+1);
1654       strcpy(rs,s);   
1655       return rs;
1656 #endif
1657
1658     case AOP_STA:
1659         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1660         return (rs);
1661         
1662     case AOP_STK:
1663 //        pCodeOp *pcop = aop->aop
1664         break;
1665
1666     }
1667
1668     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1669     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1670            "aopget got unsupported aop->type");
1671     exit(0);
1672 }
1673
1674
1675
1676 /* lock has the following meaning: When allocating temporary registers
1677  * for stack variables storage, the value of the temporary register is
1678  * saved on stack. Its value is restored at the end. This procedure is
1679  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1680  * a possibility that before a call to pic16_aopOp, a temporary register
1681  * is allocated for a while and it is freed after some time, this will
1682  * mess the stack and values will not be restored properly. So use lock=1
1683  * to allocate temporary registers used internally by the programmer, and
1684  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1685  * to inform the compiler developer about a possible bug. This is an internal
1686  * feature for developing the compiler -- VR */
1687  
1688 int _TempReg_lock = 0;
1689 /*-----------------------------------------------------------------*/
1690 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1691 /*-----------------------------------------------------------------*/
1692 pCodeOp *pic16_popGetTempReg(int lock)
1693 {
1694   pCodeOp *pcop=NULL;
1695   symbol *cfunc;
1696
1697 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1698     if(_TempReg_lock) {
1699 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1700     }
1701     
1702     _TempReg_lock += lock;
1703     
1704     cfunc = currFunc;
1705     currFunc = NULL;
1706
1707 #if 0
1708         {
1709           regs *rr;
1710           int i;
1711
1712                 /* this code might seem better but it does the *same* job with
1713                  * the old code, it all depends on ralloc.c to get a free/unused
1714                  * register */
1715          
1716                 i=0;
1717                 while(i < pic16_nRegs) {
1718                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1719                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1720                         if((!rr || (rr && rr->isFree))
1721                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1722                                 pcop = pic16_newpCodeOpReg( i );
1723                                 PCOR(pcop)->r->wasUsed = 1;
1724                                 PCOR(pcop)->r->isFree = 0;
1725                                 break;
1726                         }
1727                         i++;
1728                 }
1729
1730                 if(pcop) {
1731                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1732                 }
1733         }
1734 #else
1735     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1736     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1737       PCOR(pcop)->r->wasUsed=1;
1738       PCOR(pcop)->r->isFree=0;
1739
1740       /* push value on stack */
1741       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1742     }
1743 #endif
1744
1745     currFunc = cfunc;
1746
1747   return pcop;
1748 }
1749
1750 /*-----------------------------------------------------------------*/
1751 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1752 /*                           is not part of f, but don't save if   */
1753 /*                           inside v                              */
1754 /*-----------------------------------------------------------------*/
1755 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1756 {
1757   pCodeOp *pcop=NULL;
1758   symbol *cfunc;
1759   int i;
1760
1761 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1762
1763     if(_TempReg_lock) {
1764 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1765     }
1766
1767     _TempReg_lock += lock;
1768
1769     cfunc = currFunc;
1770     currFunc = NULL;
1771
1772     i = bitVectFirstBit(f);
1773     while(i < 128) {
1774
1775       /* bypass registers that are used by function */
1776       if(!bitVectBitValue(f, i)) {
1777       
1778         /* bypass registers that are already allocated for stack access */
1779         if(!bitVectBitValue(v, i))  {
1780         
1781 //          debugf("getting register rIdx = %d\n", i);
1782           /* ok, get the operand */
1783           pcop = pic16_newpCodeOpReg( i );
1784     
1785           /* should never by NULL */
1786           assert( pcop != NULL );
1787
1788           
1789           /* sanity check */
1790           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1791             int found=0;
1792             
1793               PCOR(pcop)->r->wasUsed=1;
1794               PCOR(pcop)->r->isFree=0;
1795
1796
1797               {
1798                 regs *sr;
1799               
1800                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1801
1802                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1803                       /* already used in previous steps, break */
1804                       found=1;          
1805                       break;
1806                     }
1807                   }
1808               }
1809
1810               /* caller takes care of the following */
1811 //              bitVectSetBit(v, i);
1812
1813               if(!found) {
1814                 /* push value on stack */
1815                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1816                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1817               }
1818           
1819             break;
1820           }
1821         }
1822       }
1823       i++;
1824     }
1825
1826     currFunc = cfunc;
1827
1828   return pcop;
1829 }
1830
1831
1832 /*-----------------------------------------------------------------*/
1833 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1834 /*-----------------------------------------------------------------*/
1835 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1836 {
1837   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1838
1839   _TempReg_lock -= lock;
1840
1841   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1842     PCOR(pcop)->r->isFree = 1;
1843
1844     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1845   }
1846 }
1847 /*-----------------------------------------------------------------*/
1848 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1849 /*-----------------------------------------------------------------*/
1850 pCodeOp *pic16_popGetLabel(int key)
1851 {
1852
1853   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1854
1855   if(key>max_key)
1856     max_key = key;
1857
1858   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1859 }
1860
1861 /*-----------------------------------------------------------------*/
1862 /* pic16_popCopyReg - copy a pcode operator                              */
1863 /*-----------------------------------------------------------------*/
1864 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1865 {
1866   pCodeOpReg *pcor;
1867
1868   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1869   memcpy (pcor, pc, sizeof (pCodeOpReg));
1870   pcor->r->wasUsed = 1;
1871   
1872   //pcor->pcop.type = pc->pcop.type;
1873   if(pc->pcop.name) {
1874     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1875       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1876   } else
1877     pcor->pcop.name = NULL;
1878
1879   //pcor->r = pc->r;
1880   //pcor->rIdx = pc->rIdx;
1881   //pcor->r->wasUsed=1;
1882   //pcor->instance = pc->instance;
1883
1884 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1885
1886   return PCOP(pcor);
1887 }
1888
1889 /*-----------------------------------------------------------------*/
1890 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1891 /*-----------------------------------------------------------------*/
1892 pCodeOp *pic16_popGetLit(int lit)
1893 {
1894   return pic16_newpCodeOpLit(lit);
1895 }
1896
1897 /* Allow for 12 bit literals (LFSR x, <here!>). */
1898 pCodeOp *pic16_popGetLit12(int lit)
1899 {
1900   return pic16_newpCodeOpLit12(lit);
1901 }
1902
1903 /*-----------------------------------------------------------------*/
1904 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1905 /*-----------------------------------------------------------------*/
1906 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1907 {
1908   return pic16_newpCodeOpLit2(lit, arg2);
1909 }
1910
1911
1912 /*-----------------------------------------------------------------*/
1913 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1914 /*-----------------------------------------------------------------*/
1915 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1916 {
1917   return pic16_newpCodeOpImmd(name, offset,index, 0);
1918 }
1919
1920
1921 /*-----------------------------------------------------------------*/
1922 /* pic16_popGet - asm operator to pcode operator conversion              */
1923 /*-----------------------------------------------------------------*/
1924 pCodeOp *pic16_popGetWithString(char *str)
1925 {
1926   pCodeOp *pcop;
1927
1928
1929   if(!str) {
1930     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1931     exit (1);
1932   }
1933
1934   pcop = pic16_newpCodeOp(str,PO_STR);
1935
1936   return pcop;
1937 }
1938
1939 /*-----------------------------------------------------------------*/
1940 /* pic16_popRegFromString -                                        */
1941 /*-----------------------------------------------------------------*/
1942 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1943 {
1944
1945   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1946   pcop->type = PO_DIR;
1947
1948   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1949   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1950
1951   if(!str)
1952     str = "BAD_STRING";
1953
1954   pcop->name = Safe_calloc(1,strlen(str)+1);
1955   strcpy(pcop->name,str);
1956
1957   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1958
1959   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1960 //  PCOR(pcop)->r->wasUsed = 1;
1961
1962   /* make sure that register doesn't exist,
1963    * and operand isn't NULL
1964    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1965   if((PCOR(pcop)->r == NULL) 
1966     && (op)
1967     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1968 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1969 //              __FUNCTION__, __LINE__, str, size, offset);
1970
1971     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1972     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1973
1974   }
1975   PCOR(pcop)->instance = offset;
1976
1977   return pcop;
1978 }
1979
1980 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1981 {
1982   pCodeOp *pcop;
1983
1984 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1985 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1986         
1987         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1988         PCOR(pcop)->rIdx = rIdx;
1989         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1990         if(!PCOR(pcop)->r)
1991                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1992                 
1993         PCOR(pcop)->r->isFree = 0;
1994         PCOR(pcop)->r->wasUsed = 1;
1995
1996         pcop->type = PCOR(pcop)->r->pc_type;
1997
1998   return pcop;
1999 }
2000
2001 /*---------------------------------------------------------------------------------*/
2002 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2003 /*                 VR 030601                                                       */
2004 /*---------------------------------------------------------------------------------*/
2005 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2006 {
2007   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2008         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2009   return PCOP(pcop2);
2010 }
2011
2012
2013
2014 /*--------------------------------------------------------------------------------.-*/
2015 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2016 /*                  VR 030601 , adapted by Hans Dorn                                */
2017 /*--------------------------------------------------------------------------------.-*/
2018 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2019 {
2020   pCodeOp2 *pcop2;
2021   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2022   return PCOP(pcop2);
2023 }
2024
2025 /*---------------------------------------------------------------------------------*/
2026 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2027 /*                     movff instruction                                           */
2028 /*---------------------------------------------------------------------------------*/
2029 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2030 {
2031   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2032         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2033
2034   return PCOP(pcop2);
2035 }
2036
2037
2038 /*-----------------------------------------------------------------*/
2039 /* pic16_popGet - asm operator to pcode operator conversion              */
2040 /*-----------------------------------------------------------------*/
2041 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2042 {
2043 //  char *s = buffer ;
2044 //  char *rs;
2045   pCodeOp *pcop;
2046
2047     FENTRY2;
2048     
2049       /* offset is greater than size then zero */
2050
2051 //    if (offset > (aop->size - 1) &&
2052 //        aop->type != AOP_LIT)
2053 //      return NULL;  //zero;
2054
2055     /* depending on type */
2056     switch (aop->type) {
2057                 case AOP_R0:
2058                 case AOP_R1:
2059                 case AOP_DPTR:
2060                 case AOP_DPTR2:
2061                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2062                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2063                         assert( 0 );
2064                         return NULL;
2065
2066                 case AOP_FSR0:
2067                 case AOP_FSR2:
2068                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2069                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2070                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2071                         PCOR(pcop)->r->wasUsed = 1;
2072                         PCOR(pcop)->r->isFree = 0;
2073       
2074                         PCOR(pcop)->instance = offset;
2075                         pcop->type = PCOR(pcop)->r->pc_type;
2076                         return (pcop);
2077
2078                 case AOP_IMMD:
2079                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2080                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2081
2082                 case AOP_STA:
2083                         /* pCodeOp is already allocated from aopForSym */
2084                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2085                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2086                         return (pcop);
2087       
2088                 case AOP_ACC:
2089                         {
2090                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2091
2092                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2093
2094                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2095         
2096                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2097                                 PCOR(pcop)->rIdx = rIdx;
2098                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2099                                 PCOR(pcop)->r->wasUsed=1;
2100                                 PCOR(pcop)->r->isFree=0;
2101
2102                                 PCOR(pcop)->instance = offset;
2103                                 pcop->type = PCOR(pcop)->r->pc_type;
2104 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2105                                 return pcop;
2106
2107
2108 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2109 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2110
2111 //      assert( 0 );
2112                         }
2113         
2114     case AOP_DIR:
2115       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2116       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2117         
2118 #if 0
2119     case AOP_PAGED:
2120       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2121       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2122 #endif
2123
2124     case AOP_REG:
2125       {
2126         int rIdx;
2127
2128 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
2129 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
2130         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2131
2132         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2133         
2134         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2135 //      pcop->type = PO_GPR_REGISTER;
2136         PCOR(pcop)->rIdx = rIdx;
2137         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2138         PCOR(pcop)->r->wasUsed=1;
2139         PCOR(pcop)->r->isFree=0;
2140
2141         PCOR(pcop)->instance = offset;
2142         pcop->type = PCOR(pcop)->r->pc_type;
2143         
2144         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2145 //      rs = aop->aopu.aop_reg[offset]->name;
2146 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2147         return pcop;
2148       }
2149
2150     case AOP_CRY:
2151         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2152
2153       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2154       PCOR(pcop)->instance = offset;
2155       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2156       //if(PCOR(pcop)->r == NULL)
2157       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2158       return pcop;
2159         
2160     case AOP_LIT:
2161         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2162       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2163
2164     case AOP_STR:
2165       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2166       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2167
2168       /*
2169       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2170       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2171       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2172       pcop->type = PCOR(pcop)->r->pc_type;
2173       pcop->name = PCOR(pcop)->r->name;
2174
2175       return pcop;
2176       */
2177
2178     case AOP_PCODE:
2179       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2180                           __LINE__, 
2181                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2182       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2183       switch( aop->aopu.pcop->type ) {
2184         case PO_DIR: PCOR(pcop)->instance += offset; break;
2185         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2186         case PO_WREG:
2187             assert (offset==0);
2188             break;
2189         default:
2190           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2191           assert( 0 );  /* should never reach here */;
2192       }
2193       return pcop;
2194     }
2195
2196     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2197            "pic16_popGet got unsupported aop->type");
2198     exit(0);
2199 }
2200 /*-----------------------------------------------------------------*/
2201 /* pic16_aopPut - puts a string for a aop                                */
2202 /*-----------------------------------------------------------------*/
2203 void pic16_aopPut (asmop *aop, char *s, int offset)
2204 {
2205     char *d = buffer ;
2206     symbol *lbl ;
2207
2208     return;
2209
2210     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2211
2212     if (aop->size && offset > ( aop->size - 1)) {
2213         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2214                "pic16_aopPut got offset > aop->size");
2215         exit(0);
2216     }
2217
2218     /* will assign value to value */
2219     /* depending on where it is ofcourse */
2220     switch (aop->type) {
2221     case AOP_DIR:
2222       if (offset) {
2223         sprintf(d,"(%s + %d)",
2224                 aop->aopu.aop_dir,offset);
2225         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2226
2227       } else
2228             sprintf(d,"%s",aop->aopu.aop_dir);
2229         
2230         if (strcmp(d,s)) {
2231           DEBUGpic16_emitcode(";","%d",__LINE__);
2232           if(strcmp(s,"W"))
2233             pic16_emitcode("movf","%s,w",s);
2234           pic16_emitcode("movwf","%s",d);
2235
2236           if(strcmp(s,"W")) {
2237             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2238             if(offset >= aop->size) {
2239               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2240               break;
2241             } else
2242               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2243           }
2244
2245           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2246
2247
2248         }
2249         break;
2250         
2251     case AOP_REG:
2252       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2253         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2254           /*
2255             if (*s == '@'           ||
2256                 strcmp(s,"r0") == 0 ||
2257                 strcmp(s,"r1") == 0 ||
2258                 strcmp(s,"r2") == 0 ||
2259                 strcmp(s,"r3") == 0 ||
2260                 strcmp(s,"r4") == 0 ||
2261                 strcmp(s,"r5") == 0 ||
2262                 strcmp(s,"r6") == 0 || 
2263                 strcmp(s,"r7") == 0 )
2264                 pic16_emitcode("mov","%s,%s  ; %d",
2265                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2266             else
2267           */
2268
2269           if(strcmp(s,"W")==0 )
2270             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2271
2272           pic16_emitcode("movwf","%s",
2273                    aop->aopu.aop_reg[offset]->name);
2274
2275           if(strcmp(s,zero)==0) {
2276             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2277
2278           } else if(strcmp(s,"W")==0) {
2279             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2280             pcop->type = PO_GPR_REGISTER;
2281
2282             PCOR(pcop)->rIdx = -1;
2283             PCOR(pcop)->r = NULL;
2284
2285             DEBUGpic16_emitcode(";","%d",__LINE__);
2286             pcop->name = Safe_strdup(s);
2287             pic16_emitpcode(POC_MOVFW,pcop);
2288             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2289           } else if(strcmp(s,one)==0) {
2290             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2291             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2292           } else {
2293             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2294           }
2295         }
2296         break;
2297         
2298     case AOP_DPTR:
2299     case AOP_DPTR2:
2300     
2301     if (aop->type == AOP_DPTR2)
2302     {
2303         genSetDPTR(1);
2304     }
2305     
2306         if (aop->code) {
2307             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2308                    "pic16_aopPut writting to code space");
2309             exit(0);
2310         }
2311         
2312         while (offset > aop->coff) {
2313             aop->coff++;
2314             pic16_emitcode ("inc","dptr");
2315         }
2316         
2317         while (offset < aop->coff) {
2318             aop->coff-- ;
2319             pic16_emitcode("lcall","__decdptr");
2320         }
2321         
2322         aop->coff = offset;
2323         
2324         /* if not in accumulater */
2325         MOVA(s);        
2326         
2327         pic16_emitcode ("movx","@dptr,a");
2328         
2329     if (aop->type == AOP_DPTR2)
2330     {
2331         genSetDPTR(0);
2332     }
2333         break;
2334         
2335     case AOP_R0:
2336     case AOP_R1:
2337         while (offset > aop->coff) {
2338             aop->coff++;
2339             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2340         }
2341         while (offset < aop->coff) {
2342             aop->coff-- ;
2343             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2344         }
2345         aop->coff = offset;
2346         
2347         if (aop->paged) {
2348             MOVA(s);           
2349             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2350             
2351         } else
2352             if (*s == '@') {
2353                 MOVA(s);
2354                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2355             } else
2356                 if (strcmp(s,"r0") == 0 ||
2357                     strcmp(s,"r1") == 0 ||
2358                     strcmp(s,"r2") == 0 ||
2359                     strcmp(s,"r3") == 0 ||
2360                     strcmp(s,"r4") == 0 ||
2361                     strcmp(s,"r5") == 0 ||
2362                     strcmp(s,"r6") == 0 || 
2363                     strcmp(s,"r7") == 0 ) {
2364                     char buffer[10];
2365                     sprintf(buffer,"a%s",s);
2366                     pic16_emitcode("mov","@%s,%s",
2367                              aop->aopu.aop_ptr->name,buffer);
2368                 } else
2369                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2370         
2371         break;
2372         
2373     case AOP_STK:
2374         if (strcmp(s,"a") == 0)
2375             pic16_emitcode("push","acc");
2376         else
2377             pic16_emitcode("push","%s",s);
2378         
2379         break;
2380         
2381     case AOP_CRY:
2382         /* if bit variable */
2383         if (!aop->aopu.aop_dir) {
2384             pic16_emitcode("clr","a");
2385             pic16_emitcode("rlc","a");
2386         } else {
2387             if (s == zero) 
2388                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2389             else
2390                 if (s == one)
2391                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2392                 else
2393                     if (!strcmp(s,"c"))
2394                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2395                     else {
2396                         lbl = newiTempLabel(NULL);
2397                         
2398                         if (strcmp(s,"a")) {
2399                             MOVA(s);
2400                         }
2401                         pic16_emitcode("clr","c");
2402                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2403                         pic16_emitcode("cpl","c");
2404                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2405                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2406                     }
2407         }
2408         break;
2409         
2410     case AOP_STR:
2411         aop->coff = offset;
2412         if (strcmp(aop->aopu.aop_str[offset],s))
2413             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2414         break;
2415         
2416     case AOP_ACC:
2417         aop->coff = offset;
2418         if (!offset && (strcmp(s,"acc") == 0))
2419             break;
2420         
2421         if (strcmp(aop->aopu.aop_str[offset],s))
2422             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2423         break;
2424
2425     default :
2426         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2427 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2428 //             "pic16_aopPut got unsupported aop->type");
2429 //      exit(0);    
2430     }    
2431
2432 }
2433
2434 /*-----------------------------------------------------------------*/
2435 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2436 /*-----------------------------------------------------------------*/
2437 void pic16_mov2w (asmop *aop, int offset)
2438 {
2439   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2440
2441   if(is_LitAOp(aop))
2442     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2443   else
2444     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2445 }
2446
2447 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2448 {
2449   if(is_LitAOp(src)) {
2450     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2451     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2452   } else {
2453     if(pic16_sameRegsOfs(src, dst, offset))return;
2454     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2455                       pic16_popGet(dst, offset)));
2456   }
2457 }
2458
2459 static void pic16_movLit2f(pCodeOp *pc, int lit)
2460 {
2461   if (0 == (lit & 0x00ff))
2462   {
2463     pic16_emitpcode (POC_CLRF, pc);
2464   } else if (0xff == (lit & 0x00ff))
2465   {
2466     pic16_emitpcode (POC_SETF, pc);
2467   } else {
2468     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2469     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2470   }
2471 }
2472
2473 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2474 {
2475   if(is_LitAOp(src)) {
2476     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2477     pic16_emitpcode(POC_MOVWF, dst);
2478   } else {
2479     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2480   }
2481 }
2482
2483 void pic16_testStackOverflow(void)
2484 {
2485 #define GSTACK_TEST_NAME        "_gstack_test"
2486
2487   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2488   
2489   {
2490     symbol *sym;
2491
2492       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2493       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2494 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2495       checkAddSym(&externs, sym);
2496   }
2497
2498 }
2499
2500 /* push pcop into stack */
2501 void pic16_pushpCodeOp(pCodeOp *pcop)
2502 {
2503 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2504   if (pcop->type == PO_LITERAL) {
2505     pic16_emitpcode(POC_MOVLW, pcop);
2506     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2507   } else {
2508     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2509   }
2510   if(pic16_options.gstack)
2511     pic16_testStackOverflow();
2512     
2513 }
2514
2515 /* pop pcop from stack */
2516 void pic16_poppCodeOp(pCodeOp *pcop)
2517 {
2518   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2519   if(pic16_options.gstack)
2520     pic16_testStackOverflow();
2521 }
2522
2523
2524 /*-----------------------------------------------------------------*/
2525 /* pushw - pushes wreg to stack                                    */
2526 /*-----------------------------------------------------------------*/
2527 void pushw(void)
2528 {
2529   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2530   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2531   if(pic16_options.gstack)
2532     pic16_testStackOverflow();
2533 }
2534
2535                 
2536 /*-----------------------------------------------------------------*/
2537 /* pushaop - pushes aop to stack                                   */
2538 /*-----------------------------------------------------------------*/
2539 void pushaop(asmop *aop, int offset)
2540 {
2541   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2542
2543   if(_G.resDirect)return;
2544   
2545   if(is_LitAOp(aop)) {
2546     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2547     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2548   } else {
2549     pic16_emitpcode(POC_MOVFF,
2550       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2551   }
2552
2553   if(pic16_options.gstack)
2554     pic16_testStackOverflow();
2555 }
2556
2557 /*-----------------------------------------------------------------*/
2558 /* popaop - pops aop from stack                                    */
2559 /*-----------------------------------------------------------------*/
2560 void popaop(asmop *aop, int offset)
2561 {
2562   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2563   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2564   if(pic16_options.gstack)
2565     pic16_testStackOverflow();
2566 }
2567
2568 void popaopidx(asmop *aop, int offset, int index)
2569 {
2570   int ofs=1;
2571
2572     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2573
2574     if(STACK_MODEL_LARGE)ofs++;
2575
2576     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2577     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2578     if(pic16_options.gstack)
2579       pic16_testStackOverflow();
2580 }
2581
2582 #if !(USE_GENERIC_SIGNED_SHIFT)
2583 /*-----------------------------------------------------------------*/
2584 /* reAdjustPreg - points a register back to where it should        */
2585 /*-----------------------------------------------------------------*/
2586 static void reAdjustPreg (asmop *aop)
2587 {
2588     int size ;
2589
2590     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2591     aop->coff = 0;
2592     if ((size = aop->size) <= 1)
2593         return ;
2594     size-- ;
2595     switch (aop->type) {
2596         case AOP_R0 :
2597         case AOP_R1 :
2598             while (size--)
2599                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2600             break;          
2601         case AOP_DPTR :
2602         case AOP_DPTR2:
2603             if (aop->type == AOP_DPTR2)
2604             {
2605                 genSetDPTR(1);
2606             } 
2607             while (size--)
2608             {
2609                 pic16_emitcode("lcall","__decdptr");
2610             }
2611                 
2612             if (aop->type == AOP_DPTR2)
2613             {
2614                 genSetDPTR(0);
2615             }                
2616             break;  
2617
2618     }   
2619
2620 }
2621 #endif
2622
2623 #if 0
2624 /*-----------------------------------------------------------------*/
2625 /* opIsGptr: returns non-zero if the passed operand is             */   
2626 /* a generic pointer type.                                         */
2627 /*-----------------------------------------------------------------*/ 
2628 static int opIsGptr(operand *op)
2629 {
2630     sym_link *type = operandType(op);
2631     
2632     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2633     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2634     {
2635         return 1;
2636     }
2637     return 0;        
2638 }
2639 #endif
2640
2641 /*-----------------------------------------------------------------*/
2642 /* pic16_getDataSize - get the operand data size                         */
2643 /*-----------------------------------------------------------------*/
2644 int pic16_getDataSize(operand *op)
2645 {
2646     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2647
2648
2649     return AOP_SIZE(op);
2650
2651     // tsd- in the pic port, the genptr size is 1, so this code here
2652     // fails. ( in the 8051 port, the size was 4).
2653 #if 0
2654     int size;
2655     size = AOP_SIZE(op);
2656     if (size == GPTRSIZE)
2657     {
2658         sym_link *type = operandType(op);
2659         if (IS_GENPTR(type))
2660         {
2661             /* generic pointer; arithmetic operations
2662              * should ignore the high byte (pointer type).
2663              */
2664             size--;
2665     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2666         }
2667     }
2668     return size;
2669 #endif
2670 }
2671
2672 /*-----------------------------------------------------------------*/
2673 /* pic16_outAcc - output Acc                                             */
2674 /*-----------------------------------------------------------------*/
2675 void pic16_outAcc(operand *result)
2676 {
2677   int size,offset;
2678   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2679   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2680
2681
2682   size = pic16_getDataSize(result);
2683   if(size){
2684     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2685     size--;
2686     offset = 1;
2687     /* unsigned or positive */
2688     while(size--)
2689       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2690   }
2691
2692 }
2693
2694 /*-----------------------------------------------------------------*/
2695 /* pic16_outBitC - output a bit C                                  */
2696 /*                 Move to result the value of Carry flag -- VR    */
2697 /*-----------------------------------------------------------------*/
2698 void pic16_outBitC(operand *result)
2699 {
2700   int i;
2701
2702     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2703
2704     /* if the result is bit */
2705     if (AOP_TYPE(result) == AOP_CRY) {
2706         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2707         pic16_aopPut(AOP(result),"c",0);
2708     } else {
2709
2710         i = AOP_SIZE(result);
2711         while(i--) {
2712                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2713         }
2714         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2715     }
2716 }
2717
2718 /*-----------------------------------------------------------------*/
2719 /* pic16_outBitOp - output a bit from Op                           */
2720 /*                 Move to result the value of set/clr op -- VR    */
2721 /*-----------------------------------------------------------------*/
2722 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2723 {
2724   int i;
2725
2726     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2727
2728     /* if the result is bit */
2729     if (AOP_TYPE(result) == AOP_CRY) {
2730         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2731         pic16_aopPut(AOP(result),"c",0);
2732     } else {
2733
2734         i = AOP_SIZE(result);
2735         while(i--) {
2736                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2737         }
2738         pic16_emitpcode(POC_RRCF, pcop);          
2739         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2740     }
2741 }
2742
2743 /*-----------------------------------------------------------------*/
2744 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2745 /*-----------------------------------------------------------------*/
2746 void pic16_toBoolean(operand *oper)
2747 {
2748     int size = AOP_SIZE(oper) - 1;
2749     int offset = 1;
2750
2751     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2752
2753     if ( AOP_TYPE(oper) != AOP_ACC) {
2754       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2755     }
2756     while (size--) {
2757       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2758     }
2759 }
2760
2761 /*-----------------------------------------------------------------*/
2762 /* genUminusFloat - unary minus for floating points                */
2763 /*-----------------------------------------------------------------*/
2764 static void genUminusFloat(operand *op,operand *result)
2765 {
2766   int size ,offset =0 ;
2767   
2768     FENTRY;
2769     /* for this we just need to flip the 
2770     first it then copy the rest in place */
2771     size = AOP_SIZE(op);
2772     assert( size == AOP_SIZE(result) );
2773
2774     while(size--) {
2775       pic16_mov2f(AOP(result), AOP(op), offset);
2776       offset++;
2777     }
2778     
2779     /* toggle the MSB's highest bit */
2780     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2781 }
2782
2783 /*-----------------------------------------------------------------*/
2784 /* genUminus - unary minus code generation                         */
2785 /*-----------------------------------------------------------------*/
2786 static void genUminus (iCode *ic)
2787 {
2788   int size, i;
2789   sym_link *optype, *rtype;
2790   symbol *label;
2791   int needLabel=0;
2792
2793     FENTRY;     
2794     
2795     /* assign asmops */
2796     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2797     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2798
2799     /* if both in bit space then special case */
2800     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2801       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2802         
2803         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2804         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2805         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2806         goto release; 
2807     } 
2808
2809     optype = operandType(IC_LEFT(ic));
2810     rtype = operandType(IC_RESULT(ic));
2811
2812
2813     /* if float then do float stuff */
2814     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2815       if(IS_FIXED(optype))
2816         debugf("implement fixed16x16 type\n", 0);
2817         
2818         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2819         goto release;
2820     }
2821
2822     /* otherwise subtract from zero by taking the 2's complement */
2823     size = AOP_SIZE(IC_LEFT(ic));
2824     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2825     label = newiTempLabel ( NULL );
2826     
2827     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2828       for (i=size-1; i > 0; i--) {
2829         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2830       } // for
2831       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2832       for (i=1; i < size; i++) {
2833         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2834         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2835       } // for
2836     } else {
2837       for (i=size-1; i >= 0; i--) {
2838         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2839         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2840       } // for
2841       if (size > 1) {
2842         for (i=0; i < size-2; i++) {
2843           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2844           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2845         } // for
2846         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2847       } // if
2848       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2849     }
2850     if (needLabel)
2851       pic16_emitpLabel (label->key);
2852
2853 release:
2854     /* release the aops */
2855     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2856     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2857 }
2858
2859 #if 0
2860 /*-----------------------------------------------------------------*/
2861 /* saveRegisters - will look for a call and save the registers     */
2862 /*-----------------------------------------------------------------*/
2863 static void saveRegisters(iCode *lic) 
2864 {
2865     int i;
2866     iCode *ic;
2867     bitVect *rsave;
2868     sym_link *dtype;
2869
2870     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2871     /* look for call */
2872     for (ic = lic ; ic ; ic = ic->next) 
2873         if (ic->op == CALL || ic->op == PCALL)
2874             break;
2875
2876     if (!ic) {
2877         fprintf(stderr,"found parameter push with no function call\n");
2878         return ;
2879     }
2880
2881     /* if the registers have been saved already then
2882     do nothing */
2883     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2884         return ;
2885
2886     /* find the registers in use at this time 
2887     and push them away to safety */
2888     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2889                           ic->rUsed);
2890
2891     ic->regsSaved = 1;
2892     if (options.useXstack) {
2893         if (bitVectBitValue(rsave,R0_IDX))
2894             pic16_emitcode("mov","b,r0");
2895         pic16_emitcode("mov","r0,%s",spname);
2896         for (i = 0 ; i < pic16_nRegs ; i++) {
2897             if (bitVectBitValue(rsave,i)) {
2898                 if (i == R0_IDX)
2899                     pic16_emitcode("mov","a,b");
2900                 else
2901                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2902                 pic16_emitcode("movx","@r0,a");
2903                 pic16_emitcode("inc","r0");
2904             }
2905         }
2906         pic16_emitcode("mov","%s,r0",spname);
2907         if (bitVectBitValue(rsave,R0_IDX))
2908             pic16_emitcode("mov","r0,b");           
2909     }// else
2910     //for (i = 0 ; i < pic16_nRegs ; i++) {
2911     //    if (bitVectBitValue(rsave,i))
2912     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2913     //}
2914
2915     dtype = operandType(IC_LEFT(ic));
2916     if (currFunc && dtype && 
2917         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2918         IFFUNC_ISISR(currFunc->type) &&
2919         !ic->bankSaved) 
2920
2921         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2922
2923 }
2924 /*-----------------------------------------------------------------*/
2925 /* unsaveRegisters - pop the pushed registers                      */
2926 /*-----------------------------------------------------------------*/
2927 static void unsaveRegisters (iCode *ic)
2928 {
2929     int i;
2930     bitVect *rsave;
2931
2932     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2933     /* find the registers in use at this time 
2934     and push them away to safety */
2935     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2936                           ic->rUsed);
2937     
2938     if (options.useXstack) {
2939         pic16_emitcode("mov","r0,%s",spname);   
2940         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2941             if (bitVectBitValue(rsave,i)) {
2942                 pic16_emitcode("dec","r0");
2943                 pic16_emitcode("movx","a,@r0");
2944                 if (i == R0_IDX)
2945                     pic16_emitcode("mov","b,a");
2946                 else
2947                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2948             }       
2949
2950         }
2951         pic16_emitcode("mov","%s,r0",spname);
2952         if (bitVectBitValue(rsave,R0_IDX))
2953             pic16_emitcode("mov","r0,b");
2954     } //else
2955     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2956     //    if (bitVectBitValue(rsave,i))
2957     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2958     //}
2959
2960 }  
2961 #endif
2962
2963 #if 0  // patch 14
2964 /*-----------------------------------------------------------------*/
2965 /* pushSide -                                                      */
2966 /*-----------------------------------------------------------------*/
2967 static void pushSide(operand * oper, int size)
2968 {
2969         int offset = 0;
2970     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2971         while (size--) {
2972                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2973                 if (AOP_TYPE(oper) != AOP_REG &&
2974                     AOP_TYPE(oper) != AOP_DIR &&
2975                     strcmp(l,"a") ) {
2976                         pic16_emitcode("mov","a,%s",l);
2977                         pic16_emitcode("push","acc");
2978                 } else
2979                         pic16_emitcode("push","%s",l);
2980         }
2981 }
2982 #endif // patch 14
2983
2984 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2985 {
2986   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2987     pic16_emitpcode(POC_MOVFW, src);
2988     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2989   } else {
2990     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2991         src, pic16_popGet(AOP(op), offset)));
2992   }
2993 }
2994
2995
2996 /*-----------------------------------------------------------------*/
2997 /* assignResultValue - assign results to oper, rescall==1 is       */
2998 /*                     called from genCall() or genPcall()         */
2999 /*-----------------------------------------------------------------*/
3000 static void assignResultValue(operand * oper, int res_size, int rescall)
3001 {
3002   int size = AOP_SIZE(oper);
3003   int offset=0;
3004   
3005     FENTRY2;
3006 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3007     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3008
3009     if(rescall) {
3010       /* assign result from a call/pcall function() */
3011                 
3012       /* function results are stored in a special order,
3013        * see top of file with Function return policy, or manual */
3014
3015       if(size <= 4) {
3016         /* 8-bits, result in WREG */
3017         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3018                         
3019         if(size > 1 && res_size > 1) {
3020           /* 16-bits, result in PRODL:WREG */
3021           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3022         }
3023                         
3024         if(size > 2 && res_size > 2) {
3025           /* 24-bits, result in PRODH:PRODL:WREG */
3026           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3027         }
3028                         
3029         if(size > 3 && res_size > 3) {
3030           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3031           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3032         }
3033
3034         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3035       
3036       } else {
3037         /* >32-bits, result on stack, and FSR0 points to beginning.
3038          * Fix stack when done */
3039         /* FIXME FIXME */
3040 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3041         while (size--) {
3042 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3043 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3044                 
3045           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3046           GpsuedoStkPtr++;
3047         }
3048                         
3049         /* fix stack */
3050         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3051         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3052         if(STACK_MODEL_LARGE) {
3053           emitSKPNC;
3054           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3055         }
3056       }                 
3057     } else {
3058       int areg = 0;             /* matching argument register */
3059       
3060 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3061       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3062
3063
3064       /* its called from genReceive (probably) -- VR */
3065       /* I hope this code will not be called from somewhere else in the future! 
3066        * We manually set the pseudo stack pointer in genReceive. - dw
3067        */
3068       if(!GpsuedoStkPtr && _G.useWreg) {
3069 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3070
3071         /* The last byte in the assignment is in W */
3072         if(areg <= GpsuedoStkPtr) {
3073           size--;
3074           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3075           offset++;
3076 //          debugf("receive from WREG\n", 0);
3077         }
3078         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3079       }
3080 //      GpsuedoStkPtr++;
3081       _G.stack_lat = AOP_SIZE(oper)-1;
3082
3083       while (size) {
3084         size--;
3085         GpsuedoStkPtr++;
3086         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3087 //        debugf("receive from STACK\n", 0);
3088         offset++;
3089       }
3090     }
3091 }
3092
3093
3094 /*-----------------------------------------------------------------*/
3095 /* genIpush - generate code for pushing this gets a little complex */
3096 /*-----------------------------------------------------------------*/
3097 static void genIpush (iCode *ic)
3098 {
3099 //  int size, offset=0;
3100
3101   FENTRY;
3102   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3103
3104   if(ic->parmPush) {
3105     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3106
3107     /* send to stack as normal */
3108     addSet(&_G.sendSet,ic);
3109 //    addSetHead(&_G.sendSet,ic);
3110     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3111   }
3112
3113         
3114 #if 0
3115     int size, offset = 0 ;
3116     char *l;
3117
3118
3119     /* if this is not a parm push : ie. it is spill push 
3120     and spill push is always done on the local stack */
3121     if (!ic->parmPush) {
3122
3123         /* and the item is spilt then do nothing */
3124         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3125             return ;
3126
3127         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3128         size = AOP_SIZE(IC_LEFT(ic));
3129         /* push it on the stack */
3130         while(size--) {
3131             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3132             if (*l == '#') {
3133                 MOVA(l);
3134                 l = "acc";
3135             }
3136             pic16_emitcode("push","%s",l);
3137         }
3138         return ;        
3139     }
3140
3141     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3142 #endif
3143 }
3144
3145 /*-----------------------------------------------------------------*/
3146 /* genIpop - recover the registers: can happen only for spilling   */
3147 /*-----------------------------------------------------------------*/
3148 static void genIpop (iCode *ic)
3149 {
3150   FENTRY;
3151   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3152 #if 0
3153     int size,offset ;
3154
3155
3156     /* if the temp was not pushed then */
3157     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3158         return ;
3159
3160     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3161     size = AOP_SIZE(IC_LEFT(ic));
3162     offset = (size-1);
3163     while (size--) 
3164         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3165                                    FALSE,TRUE));
3166
3167     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3168 #endif
3169 }
3170
3171 #if 0
3172 /*-----------------------------------------------------------------*/
3173 /* unsaverbank - restores the resgister bank from stack            */
3174 /*-----------------------------------------------------------------*/
3175 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3176 {
3177   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3178 #if 0
3179     int i;
3180     asmop *aop ;
3181     regs *r = NULL;
3182
3183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3184     if (popPsw) {
3185         if (options.useXstack) {
3186             aop = newAsmop(0);
3187             r = getFreePtr(ic,&aop,FALSE);
3188             
3189             
3190             pic16_emitcode("mov","%s,_spx",r->name);
3191             pic16_emitcode("movx","a,@%s",r->name);
3192             pic16_emitcode("mov","psw,a");
3193             pic16_emitcode("dec","%s",r->name);
3194             
3195         }else
3196             pic16_emitcode ("pop","psw");
3197     }
3198
3199     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3200         if (options.useXstack) {       
3201             pic16_emitcode("movx","a,@%s",r->name);
3202             //pic16_emitcode("mov","(%s+%d),a",
3203             //       regspic16[i].base,8*bank+regspic16[i].offset);
3204             pic16_emitcode("dec","%s",r->name);
3205
3206         } else 
3207           pic16_emitcode("pop",""); //"(%s+%d)",
3208         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3209     }
3210
3211     if (options.useXstack) {
3212
3213         pic16_emitcode("mov","_spx,%s",r->name);
3214         pic16_freeAsmop(NULL,aop,ic,TRUE);
3215
3216     }
3217 #endif 
3218 }
3219
3220 /*-----------------------------------------------------------------*/
3221 /* saverbank - saves an entire register bank on the stack          */
3222 /*-----------------------------------------------------------------*/
3223 static void saverbank (int bank, iCode *ic, bool pushPsw)
3224 {
3225   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3226 #if 0
3227     int i;
3228     asmop *aop ;
3229     regs *r = NULL;
3230
3231     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3232     if (options.useXstack) {
3233
3234         aop = newAsmop(0);
3235         r = getFreePtr(ic,&aop,FALSE);  
3236         pic16_emitcode("mov","%s,_spx",r->name);
3237
3238     }
3239
3240     for (i = 0 ; i < pic16_nRegs ;i++) {
3241         if (options.useXstack) {
3242             pic16_emitcode("inc","%s",r->name);
3243             //pic16_emitcode("mov","a,(%s+%d)",
3244             //         regspic16[i].base,8*bank+regspic16[i].offset);
3245             pic16_emitcode("movx","@%s,a",r->name);           
3246         } else 
3247           pic16_emitcode("push","");// "(%s+%d)",
3248                      //regspic16[i].base,8*bank+regspic16[i].offset);
3249     }
3250     
3251     if (pushPsw) {
3252         if (options.useXstack) {
3253             pic16_emitcode("mov","a,psw");
3254             pic16_emitcode("movx","@%s,a",r->name);     
3255             pic16_emitcode("inc","%s",r->name);
3256             pic16_emitcode("mov","_spx,%s",r->name);       
3257             pic16_freeAsmop (NULL,aop,ic,TRUE);
3258             
3259         } else
3260             pic16_emitcode("push","psw");
3261         
3262         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3263     }
3264     ic->bankSaved = 1;
3265 #endif
3266 }
3267 #endif  /* 0 */
3268
3269
3270 static int wparamCmp(void *p1, void *p2)
3271 {
3272   return (!strcmp((char *)p1, (char *)p2));
3273 }
3274
3275 int inWparamList(char *s)
3276 {
3277   return isinSetWith(wparamList, s, wparamCmp);
3278
3279
3280
3281 /*-----------------------------------------------------------------*/
3282 /* genCall - generates a call statement                            */
3283 /*-----------------------------------------------------------------*/
3284 static void genCall (iCode *ic)
3285 {
3286   sym_link *ftype;   
3287   int stackParms=0;
3288   int use_wreg=0;
3289   int inwparam=0;
3290   char *fname;
3291   
3292     FENTRY;
3293
3294     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3295     /* if caller saves & we have not saved then */
3296 //    if (!ic->regsSaved)
3297 //      saveRegisters(ic);
3298
3299         /* initialise stackParms for IPUSH pushes */
3300 //      stackParms = psuedoStkPtr;
3301 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3302     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3303     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3304
3305 #if 0
3306     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3307 #endif
3308
3309     /* if send set is not empty the assign */
3310     if (_G.sendSet) {
3311       iCode *sic;
3312       int psuedoStkPtr=-1; 
3313       int firstTimeThruLoop = 1;
3314
3315
3316         /* reverse sendSet if function is not reentrant */
3317         if(!IFFUNC_ISREENT(ftype))
3318           _G.sendSet = reverseSet(_G.sendSet);
3319
3320         /* First figure how many parameters are getting passed */
3321         stackParms = 0;
3322         use_wreg = 0;
3323         
3324         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3325           int size;
3326 //          int offset = 0;
3327
3328             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3329             size = AOP_SIZE(IC_LEFT(sic));
3330
3331             stackParms += size;
3332
3333             /* pass the last byte through WREG */
3334             if(inwparam) {
3335
3336               while (size--) {
3337                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3338                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3339                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3340
3341                 if(!firstTimeThruLoop) {
3342                   /* If this is not the first time we've been through the loop
3343                    * then we need to save the parameter in a temporary
3344                    * register. The last byte of the last parameter is
3345                    * passed in W. */
3346
3347                   pushw();
3348 //                  --psuedoStkPtr;             // sanity check
3349                   use_wreg = 1;
3350                 }
3351                 
3352                 firstTimeThruLoop=0;
3353
3354                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3355
3356 //                offset++;
3357               }
3358             } else {
3359               /* all arguments are passed via stack */
3360               use_wreg = 0;
3361
3362               while (size--) {
3363                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3364                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3365                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3366
3367 //                pushaop(AOP(IC_LEFT(sic)), size);
3368                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3369                                 
3370                 if(!_G.resDirect)
3371                   pushw();
3372               }
3373             }
3374
3375             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3376           }
3377
3378           if(inwparam) {
3379             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3380               pushw();  /* save last parameter to stack if functions has varargs */
3381               use_wreg = 0;
3382             } else
3383               use_wreg = 1;
3384           } else use_wreg = 0;
3385
3386           _G.stackRegSet = _G.sendSet;
3387           _G.sendSet = NULL;
3388     }
3389
3390     /* make the call */
3391     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3392
3393     GpsuedoStkPtr=0;
3394     
3395     /* if we need to assign a result value */
3396     if ((IS_ITEMP(IC_RESULT(ic))
3397           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3398               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3399         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3400
3401       _G.accInUse++;
3402       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3403       _G.accInUse--;
3404
3405       /* Must not assign an 8-bit result to a 16-bit variable;
3406        * this would use (used...) the uninitialized PRODL! */
3407       /* FIXME: Need a proper way to obtain size of function result type,
3408        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3409       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3410
3411       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3412                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3413                 
3414       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3415     }
3416
3417     if(!stackParms && ic->parmBytes) {
3418       stackParms = ic->parmBytes;
3419     }
3420       
3421     stackParms -= use_wreg;
3422     
3423     if(stackParms>0) {
3424       if(stackParms == 1) {
3425         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3426       } else {
3427         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3428         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3429       }
3430       if(STACK_MODEL_LARGE) {
3431         emitSKPNC;
3432         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3433       }
3434     }
3435
3436 #if 0
3437     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3438 #endif
3439
3440     /* adjust the stack for parameters if required */
3441 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3442
3443 #if 0
3444       /* if register bank was saved then pop them */
3445       if (ic->bankSaved)
3446         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3447
3448       /* if we hade saved some registers then unsave them */
3449       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3450         unsaveRegisters (ic);
3451 #endif
3452 }
3453
3454
3455
3456 /*-----------------------------------------------------------------*/
3457 /* genPcall - generates a call by pointer statement                */
3458 /*            new version, created from genCall - HJD              */
3459 /*-----------------------------------------------------------------*/
3460 static void genPcall (iCode *ic)
3461 {
3462   sym_link *fntype;
3463   int stackParms=0;
3464   symbol *retlbl = newiTempLabel(NULL);
3465   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3466   
3467     FENTRY;
3468
3469     fntype = operandType( IC_LEFT(ic) )->next;
3470
3471     /* if send set is not empty the assign */
3472     if (_G.sendSet) {
3473       iCode *sic;
3474       int psuedoStkPtr=-1; 
3475
3476       /* reverse sendSet if function is not reentrant */
3477       if(!IFFUNC_ISREENT(fntype))
3478         _G.sendSet = reverseSet(_G.sendSet);
3479
3480       stackParms = 0;
3481       
3482       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3483         int size;
3484
3485           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3486           size = AOP_SIZE(IC_LEFT(sic));
3487           stackParms += size;
3488
3489           /* all parameters are passed via stack, since WREG is clobbered
3490            * by the calling sequence */
3491           while (size--) {
3492             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3493             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3494             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3495
3496             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3497             pushw();
3498           }
3499
3500           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3501       }
3502
3503       _G.stackRegSet = _G.sendSet;
3504       _G.sendSet = NULL;
3505     }
3506
3507     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3508
3509     // push return address
3510     // push $ on return stack, then replace with retlbl
3511
3512     /* Thanks to Thorsten Klose for pointing out that the following
3513      * snippet should be interrupt safe */
3514     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3515     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3516
3517     pic16_emitpcodeNULLop(POC_PUSH);
3518
3519     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3520     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3521     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3522     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3523     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3524     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3525
3526
3527     /* restore interrupt control register */
3528     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3530
3531     /* make the call by writing the pointer into pc */
3532     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3533     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3534
3535     // note: MOVFF to PCL not allowed
3536     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3537     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3538
3539
3540     /* return address is here: (X) */
3541     pic16_emitpLabelFORCE(retlbl->key);
3542
3543     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3544
3545     GpsuedoStkPtr=0;
3546     /* if we need assign a result value */
3547     if ((IS_ITEMP(IC_RESULT(ic))
3548           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3549               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3550         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3551
3552       _G.accInUse++;
3553       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3554       _G.accInUse--;
3555
3556       /* FIXME: Need proper way to obtain the function result's type.
3557        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3558       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3559
3560       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3561               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3562                 
3563       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3564     }
3565
3566 //    stackParms -= use_wreg;
3567     
3568     if(stackParms>0) {
3569       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3570       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3571       if(STACK_MODEL_LARGE) {
3572         emitSKPNC;
3573         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3574       }
3575     }
3576 }
3577
3578 /*-----------------------------------------------------------------*/
3579 /* resultRemat - result  is rematerializable                       */
3580 /*-----------------------------------------------------------------*/
3581 static int resultRemat (iCode *ic)
3582 {
3583   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3584   if (SKIP_IC(ic) || ic->op == IFX)
3585     return 0;
3586
3587   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3588     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3589     if (sym->remat && !POINTER_SET(ic)) 
3590       return 1;
3591   }
3592
3593   return 0;
3594 }
3595
3596 #if defined(__BORLANDC__) || defined(_MSC_VER)
3597 #define STRCASECMP stricmp
3598 #else
3599 #define STRCASECMP strcasecmp
3600 #endif
3601
3602 #if 0
3603 /*-----------------------------------------------------------------*/
3604 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3605 /*-----------------------------------------------------------------*/
3606 static bool inExcludeList(char *s)
3607 {
3608   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3609     int i =0;
3610     
3611     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3612     if (options.excludeRegs[i] &&
3613     STRCASECMP(options.excludeRegs[i],"none") == 0)
3614         return FALSE ;
3615
3616     for ( i = 0 ; options.excludeRegs[i]; i++) {
3617         if (options.excludeRegs[i] &&
3618         STRCASECMP(s,options.excludeRegs[i]) == 0)
3619             return TRUE;
3620     }
3621     return FALSE ;
3622 }
3623 #endif
3624
3625 /*-----------------------------------------------------------------*/
3626 /* genFunction - generated code for function entry                 */
3627 /*-----------------------------------------------------------------*/
3628 static void genFunction (iCode *ic)
3629 {
3630   symbol *sym;
3631   sym_link *ftype;
3632   
3633     FENTRY;
3634     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3635
3636     pic16_labelOffset += (max_key+4);
3637     max_key=0;
3638     GpsuedoStkPtr=0;
3639     _G.nRegsSaved = 0;
3640         
3641     ftype = operandType(IC_LEFT(ic));
3642     sym = OP_SYMBOL(IC_LEFT(ic));
3643
3644     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3645       /* create an absolute section at the interrupt vector:
3646        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3647       symbol *asym;
3648       char asymname[128];
3649       pBlock *apb;
3650
3651 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3652
3653         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3654           sprintf(asymname, "ivec_%s", sym->name);
3655         else
3656           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3657   
3658         /* when an interrupt is declared as naked, do not emit the special
3659          * wrapper segment at vector address. The user should take care for
3660          * this instead. -- VR */
3661
3662         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3663           asym = newSymbol(asymname, 0);
3664           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3665           pic16_addpBlock( apb );
3666
3667           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3668           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3669           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3670           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3671           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3672                 
3673           /* mark the end of this tiny function */
3674           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3675         } else {
3676           sprintf(asymname, "%s", sym->rname);
3677         }
3678
3679         {
3680           absSym *abSym;
3681
3682             abSym = Safe_calloc(1, sizeof(absSym));
3683             strcpy(abSym->name, asymname);
3684
3685             switch( FUNC_INTNO(sym->type) ) {
3686               case 0: abSym->address = 0x000000; break;
3687               case 1: abSym->address = 0x000008; break;
3688               case 2: abSym->address = 0x000018; break;
3689               
3690               default:
3691 //                fprintf(stderr, "no interrupt number is given\n");
3692                 abSym->address = -1; break;
3693             }
3694
3695             /* relocate interrupt vectors if needed */
3696             if(abSym->address != -1)
3697               abSym->address += pic16_options.ivt_loc;
3698
3699             addSet(&absSymSet, abSym);
3700         }
3701     }
3702
3703     /* create the function header */
3704     pic16_emitcode(";","-----------------------------------------");
3705     pic16_emitcode(";"," function %s",sym->name);
3706     pic16_emitcode(";","-----------------------------------------");
3707
3708     /* prevent this symbol from being emitted as 'extern' */
3709     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3710
3711     pic16_emitcode("","%s:",sym->rname);
3712     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3713
3714     {
3715       absSym *ab;
3716
3717         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3718           if(!strcmp(ab->name, sym->rname)) {
3719             pic16_pBlockConvert2Absolute(pb);
3720             break;
3721           }
3722         }
3723     }
3724
3725     if(IFFUNC_ISNAKED(ftype)) {
3726       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3727       return;
3728     }
3729         
3730     /* if critical function then turn interrupts off */
3731     if (IFFUNC_ISCRITICAL(ftype)) {
3732       //pic16_emitcode("clr","ea");
3733     }
3734
3735     currFunc = sym;             /* update the currFunc symbol */
3736     _G.fregsUsed = sym->regsUsed;
3737     _G.sregsAlloc = newBitVect(128);
3738     
3739
3740     /* if this is an interrupt service routine then
3741      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3742     if (IFFUNC_ISISR(sym->type)) {
3743         _G.usefastretfie = 1;   /* use shadow registers by default */
3744         
3745         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3746         if(!FUNC_ISSHADOWREGS(sym->type)) {
3747           /* do not save WREG,STATUS,BSR for high priority interrupts
3748            * because they are stored in the hardware shadow registers already */
3749           _G.usefastretfie = 0;
3750           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3751           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3752           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3753         }
3754
3755         /* these should really be optimized somehow, because not all
3756          * interrupt handlers modify them */
3757         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3758         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3759         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3760         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3761         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3762         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3763         
3764 //        pic16_pBlockConvert2ISR(pb);
3765     }
3766
3767     /* emit code to setup stack frame if user enabled,
3768      * and function is not main() */
3769     
3770 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3771     if(strcmp(sym->name, "main")) {
3772       if(0 
3773         || !options.ommitFramePtr 
3774 //        || sym->regsUsed
3775         || IFFUNC_ARGS(sym->type)
3776         || FUNC_HASSTACKPARM(sym->etype)
3777         ) {
3778         /* setup the stack frame */
3779         if(STACK_MODEL_LARGE)
3780           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3781         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3782
3783         if(STACK_MODEL_LARGE)
3784           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3785         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3786       }
3787     }
3788
3789     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3790           && sym->stack) {
3791
3792       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3793
3794       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3795       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3796       emitSKPC;
3797       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3798     }
3799           
3800     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3801       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3802         _G.useWreg = 0;
3803       else
3804         _G.useWreg = 1;
3805     } else
3806       _G.useWreg = 0;
3807
3808     /* if callee-save to be used for this function
3809      * then save the registers being used in this function */
3810 //    if (IFFUNC_CALLEESAVES(sym->type))
3811     if(strcmp(sym->name, "main")) {
3812       int i;
3813
3814         /* if any registers used */
3815         if (sym->regsUsed) {
3816                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3817
3818           if(!xinst) {
3819             /* save the registers used */
3820             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3821             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3822               if (bitVectBitValue(sym->regsUsed,i)) {
3823 #if 0
3824                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3825 #endif
3826                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3827                 _G.nRegsSaved++;
3828
3829                 if(!pic16_regWithIdx(i)->wasUsed) {
3830                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3831                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3832                   pic16_regWithIdx(i)->wasUsed = 1;
3833                 }
3834               }
3835             }
3836           } else {
3837             
3838             /* xinst */
3839             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3840             for(i=0;i<sym->regsUsed->size;i++) {
3841               if(bitVectBitValue(sym->regsUsed, i)) {
3842                 _G.nRegsSaved++;
3843               }
3844             }
3845                         
3846 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3847           }
3848
3849           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3850
3851         }
3852     }
3853         
3854     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3855 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3856 }
3857
3858 /*-----------------------------------------------------------------*/
3859 /* genEndFunction - generates epilogue for functions               */
3860 /*-----------------------------------------------------------------*/
3861 static void genEndFunction (iCode *ic)
3862 {
3863   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3864
3865     FENTRY;
3866
3867     if(IFFUNC_ISNAKED(sym->type)) {
3868       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3869       return;
3870     }
3871
3872     _G.stack_lat = 0;
3873
3874     /* add code for ISCRITICAL */
3875     if(IFFUNC_ISCRITICAL(sym->type)) {
3876       /* if critical function, turn on interrupts */
3877       
3878       /* TODO: add code here -- VR */
3879     }
3880     
3881 //    sym->regsUsed = _G.fregsUsed;
3882     
3883     /* now we need to restore the registers */
3884     /* if any registers used */
3885
3886     /* first restore registers that might be used for stack access */
3887     if(_G.sregsAllocSet) {
3888     regs *sr;
3889     
3890       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3891       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3892         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3893       }
3894     }
3895
3896     if (strcmp(sym->name, "main") && sym->regsUsed) {
3897       int i;
3898
3899         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3900         /* restore registers used */
3901         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3902         for ( i = sym->regsUsed->size; i >= 0; i--) {
3903           if (bitVectBitValue(sym->regsUsed,i)) {
3904             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3905             _G.nRegsSaved--;
3906           }
3907         }
3908         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3909     }
3910
3911       
3912
3913     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3914           && sym->stack) {
3915       if (sym->stack == 1) {
3916         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3917         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3918       } else {
3919         // we have to add more than one...
3920         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3921         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3922         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3923         emitSKPNC;
3924         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3925         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3926         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3927       }
3928     }
3929
3930     if(strcmp(sym->name, "main")) {
3931       if(0
3932         || !options.ommitFramePtr
3933 //        || sym->regsUsed
3934         || IFFUNC_ARGS(sym->type)
3935         || FUNC_HASSTACKPARM(sym->etype)
3936         ) {
3937         /* restore stack frame */
3938         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3939         if(STACK_MODEL_LARGE)
3940           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3941       }
3942     }
3943
3944     _G.useWreg = 0;
3945
3946     if (IFFUNC_ISISR(sym->type)) {
3947       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3948       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3949       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3950       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3951       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3952       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3953
3954       if(!FUNC_ISSHADOWREGS(sym->type)) {
3955         /* do not restore interrupt vector for WREG,STATUS,BSR
3956          * for high priority interrupt, see genFunction */
3957         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3958         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3959         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3960       }
3961 //      _G.interruptvector = 0;         /* sanity check */
3962
3963
3964       /* if debug then send end of function */
3965 /*      if (options.debug && currFunc)  */
3966       if (currFunc) {
3967         debugFile->writeEndFunction (currFunc, ic, 1);
3968       }
3969         
3970       if(_G.usefastretfie)
3971         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3972       else
3973         pic16_emitpcodeNULLop(POC_RETFIE);
3974
3975       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3976       
3977       _G.usefastretfie = 0;
3978       return;
3979     }
3980
3981     if (IFFUNC_ISCRITICAL(sym->type)) {
3982       pic16_emitcode("setb","ea");
3983     }
3984
3985     /* if debug then send end of function */
3986     if (currFunc) {
3987       debugFile->writeEndFunction (currFunc, ic, 1);
3988     }
3989
3990     /* insert code to restore stack frame, if user enabled it
3991      * and function is not main() */
3992          
3993
3994     pic16_emitpcodeNULLop(POC_RETURN);
3995
3996     /* Mark the end of a function */
3997     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3998 }
3999
4000
4001 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4002 {
4003   unsigned long lit=1;
4004   operand *op;
4005   
4006     op = IC_LEFT(ic);
4007   
4008     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4009     if(AOP_TYPE(op) == AOP_LIT) {
4010       if(!IS_FLOAT(operandType( op ))) {
4011         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4012       } else {
4013         union {
4014           unsigned long lit_int;
4015           float lit_float;
4016         } info;
4017         
4018         /* take care if literal is a float */
4019         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4020         lit = info.lit_int;
4021       }
4022     }
4023
4024     if (AOP_TYPE(op) == AOP_LIT) {
4025       /* FIXME: broken for
4026        *   char __at(0x456) foo;
4027        *   return &foo;
4028        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4029       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4030     } else if (AOP_TYPE(op) == AOP_PCODE
4031                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4032       /* char *s= "aaa"; return s; */
4033       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4034        *      that the generic pointer is interpreted correctly
4035        *      as referring to __code space, but this is fragile! */
4036       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4037       /* XXX: should check that dest != WREG */
4038       pic16_emitpcode(POC_MOVWF, dest);
4039     } else {
4040       if(dest->type == PO_WREG && (offset == 0)) {
4041         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4042         return;
4043       }
4044       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4045     }
4046 }
4047
4048 /*-----------------------------------------------------------------*/
4049 /* genRet - generate code for return statement                     */
4050 /*-----------------------------------------------------------------*/
4051 static void genRet (iCode *ic)
4052 {
4053   int size;
4054   operand *left;
4055
4056     FENTRY;
4057         /* if we have no return value then
4058          * just generate the "ret" */
4059         
4060         if (!IC_LEFT(ic)) 
4061                 goto jumpret;       
4062     
4063         /* we have something to return then
4064          * move the return value into place */
4065         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4066         size = AOP_SIZE(IC_LEFT(ic));
4067
4068         if(size <= 4) {
4069           if(size>3)
4070             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4071           
4072           if(size>2)
4073             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4074
4075           if(size>1)
4076             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4077           
4078           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4079
4080         } else {
4081                 /* >32-bits, setup stack and FSR0 */
4082                 while (size--) {
4083 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4084 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4085
4086                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4087
4088 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4089                         GpsuedoStkPtr++;
4090                 }
4091                         
4092                 /* setup FSR0 */
4093                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4094                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4095
4096                 if(STACK_MODEL_LARGE) {
4097                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4098                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4099                 } else {
4100                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4101                 }
4102         }
4103                                 
4104 #if 0
4105         /* old code, left here for reference -- VR */    
4106         while (size--) {
4107           char *l ;
4108
4109                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4110                         /* #NOCHANGE */
4111                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4112                         pic16_emitpcomment("push %s",l);
4113                         pushed++;
4114                 } else {
4115                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4116                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4117                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4118                         
4119                         if (strcmp(fReturn[offset],l)) {
4120                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4121                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4122                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4123                                 } else {
4124                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4125                                 }
4126                                 
4127                                 if(size) {
4128                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4129                                 }
4130                                 offset++;
4131                         }
4132                 }
4133         }    
4134
4135         if (pushed) {
4136                 while(pushed) {
4137                         pushed--;
4138                         if (strcmp(fReturn[pushed],"a"))
4139                                 pic16_emitcode("pop",fReturn[pushed]);
4140                         else
4141                                 pic16_emitcode("pop","acc");
4142                 }
4143         }
4144 #endif
4145
4146
4147         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4148     
4149 jumpret:
4150         /* generate a jump to the return label
4151          * if the next is not the return statement */
4152         if (!(ic->next && ic->next->op == LABEL
4153                 && IC_LABEL(ic->next) == returnLabel)) {
4154         
4155                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4156                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4157         }
4158 }
4159
4160 /*-----------------------------------------------------------------*/
4161 /* genLabel - generates a label                                    */
4162 /*-----------------------------------------------------------------*/
4163 static void genLabel (iCode *ic)
4164 {
4165   FENTRY;
4166
4167   /* special case never generate */
4168   if (IC_LABEL(ic) == entryLabel)
4169     return ;
4170
4171   pic16_emitpLabel(IC_LABEL(ic)->key);
4172 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4173 }
4174
4175 /*-----------------------------------------------------------------*/
4176 /* genGoto - generates a goto                                      */
4177 /*-----------------------------------------------------------------*/
4178 //tsd
4179 static void genGoto (iCode *ic)
4180 {
4181   FENTRY;
4182   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4183 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4184 }
4185
4186
4187 /*-----------------------------------------------------------------*/
4188 /* genMultbits :- multiplication of bits                           */
4189 /*-----------------------------------------------------------------*/
4190 static void genMultbits (operand *left, 
4191                          operand *right, 
4192                          operand *result)
4193 {
4194   FENTRY;
4195
4196   if(!pic16_sameRegs(AOP(result),AOP(right)))
4197     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4198
4199   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4200   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4201   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4202
4203 }
4204
4205
4206 /*-----------------------------------------------------------------*/
4207 /* genMultOneByte : 8 bit multiplication & division                */
4208 /*-----------------------------------------------------------------*/
4209 static void genMultOneByte (operand *left,
4210                             operand *right,
4211                             operand *result)
4212 {
4213
4214   FENTRY;
4215   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4216   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4217
4218   /* (if two literals, the value is computed before) */
4219   /* if one literal, literal on the right */
4220   if (AOP_TYPE(left) == AOP_LIT){
4221     operand *t = right;
4222     right = left;
4223     left = t;
4224   }
4225
4226         /* size is already checked in genMult == 1 */
4227 //      size = AOP_SIZE(result);
4228
4229         if (AOP_TYPE(right) == AOP_LIT){
4230                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4231                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4232                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4233                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4234         } else {
4235                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4236                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4237                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4238                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4239         }
4240         
4241         pic16_genMult8X8_n (left, right,result);
4242 }
4243
4244 #if 0
4245 /*-----------------------------------------------------------------*/
4246 /* genMultOneWord : 16 bit multiplication                          */
4247 /*-----------------------------------------------------------------*/
4248 static void genMultOneWord (operand *left,
4249                             operand *right,
4250                             operand *result)
4251 {
4252   FENTRY;
4253   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4254   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4255
4256   /* (if two literals, the value is computed before)
4257    * if one literal, literal on the right */
4258   if (AOP_TYPE(left) == AOP_LIT){
4259     operand *t = right;
4260     right = left;
4261     left = t;
4262   }
4263
4264   /* size is checked already == 2 */
4265 //  size = AOP_SIZE(result);
4266
4267   if (AOP_TYPE(right) == AOP_LIT) {
4268     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4269       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4270       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4271       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4272   } else {
4273     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4274       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4275       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4276       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4277   }
4278         
4279   pic16_genMult16X16_16(left, right,result);
4280 }
4281 #endif
4282
4283 #if 0
4284 /*-----------------------------------------------------------------*/
4285 /* genMultOneLong : 32 bit multiplication                          */
4286 /*-----------------------------------------------------------------*/
4287 static void genMultOneLong (operand *left,
4288                             operand *right,
4289                             operand *result)
4290 {
4291   FENTRY;
4292   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4293   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4294
4295   /* (if two literals, the value is computed before)
4296    * if one literal, literal on the right */
4297   if (AOP_TYPE(left) == AOP_LIT){
4298     operand *t = right;
4299     right = left;
4300     left = t;
4301   }
4302
4303   /* size is checked already == 4 */
4304 //  size = AOP_SIZE(result);
4305
4306   if (AOP_TYPE(right) == AOP_LIT) {
4307     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4308         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4309         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4310         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4311   } else {
4312     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4313         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4314         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4315         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4316   }
4317         
4318   pic16_genMult32X32_32(left, right,result);
4319 }
4320 #endif
4321
4322
4323
4324 /*-----------------------------------------------------------------*/
4325 /* genMult - generates code for multiplication                     */
4326 /*-----------------------------------------------------------------*/
4327 static void genMult (iCode *ic)
4328 {
4329   operand *left = IC_LEFT(ic);
4330   operand *right = IC_RIGHT(ic);
4331   operand *result= IC_RESULT(ic);   
4332
4333     FENTRY;
4334         /* assign the amsops */
4335         pic16_aopOp (left,ic,FALSE);
4336         pic16_aopOp (right,ic,FALSE);
4337         pic16_aopOp (result,ic,TRUE);
4338
4339         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4340
4341         /* special cases first *
4342         * both are bits */
4343         if (AOP_TYPE(left) == AOP_CRY
4344                 && AOP_TYPE(right)== AOP_CRY) {
4345                 genMultbits(left,right,result);
4346           goto release ;
4347         }
4348
4349         /* if both are of size == 1 */
4350         if(AOP_SIZE(left) == 1
4351                 && AOP_SIZE(right) == 1) {
4352                 genMultOneByte(left,right,result);
4353           goto release ;
4354         }
4355
4356 #if 0
4357         /* if both are of size == 2 */
4358         if(AOP_SIZE(left) == 2
4359                 && AOP_SIZE(right) == 2) {
4360                 genMultOneWord(left, right, result);
4361           goto release;
4362         }
4363         
4364         /* if both are of size == 4 */
4365         if(AOP_SIZE(left) == 4
4366                 && AOP_SIZE(right) == 4) {
4367                 genMultOneLong(left, right, result);
4368           goto release;
4369         }
4370 #endif
4371
4372         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4373         assert( !"Multiplication should have been transformed into function call!" );
4374
4375         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4376
4377
4378         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4379         /* should have been converted to function call */
4380         assert(0) ;
4381
4382 release :
4383         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4385         pic16_freeAsmop(result,NULL,ic,TRUE); 
4386 }
4387
4388 #if 0
4389 /*-----------------------------------------------------------------*/
4390 /* genDivbits :- division of bits                                  */
4391 /*-----------------------------------------------------------------*/
4392 static void genDivbits (operand *left, 
4393                         operand *right, 
4394                         operand *result)
4395 {
4396   char *l;
4397
4398     FENTRY;
4399     /* the result must be bit */    
4400     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4401     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4402
4403     MOVA(l);    
4404
4405     pic16_emitcode("div","ab");
4406     pic16_emitcode("rrc","a");
4407     pic16_aopPut(AOP(result),"c",0);
4408 }
4409
4410 /*-----------------------------------------------------------------*/
4411 /* genDivOneByte : 8 bit division                                  */
4412 /*-----------------------------------------------------------------*/
4413 static void genDivOneByte (operand *left,
4414                            operand *right,
4415                            operand *result)
4416 {
4417   sym_link *opetype = operandType(result);
4418   char *l ;
4419   symbol *lbl ;
4420   int size,offset;
4421
4422         /* result = divident / divisor
4423          * - divident may be a register or a literal,
4424          * - divisor may be a register or a literal,
4425          * so there are 3 cases (literal / literal is optimized
4426          * by the front-end) to handle.
4427          * In addition we must handle signed and unsigned, which
4428          * result in 6 final different cases -- VR */
4429
4430     FENTRY;
4431     
4432     size = AOP_SIZE(result) - 1;
4433     offset = 1;
4434     /* signed or unsigned */
4435     if (SPEC_USIGN(opetype)) {
4436       pCodeOp *pct1,    /* count */
4437                 *pct2,  /* reste */
4438                 *pct3;  /* temp */
4439       symbol *label1, *label2, *label3;;
4440
4441
4442         /* unsigned is easy */
4443
4444         pct1 = pic16_popGetTempReg(1);
4445         pct2 = pic16_popGetTempReg(1);
4446         pct3 = pic16_popGetTempReg(1);
4447         
4448         label1 = newiTempLabel(NULL);
4449         label2 = newiTempLabel(NULL);
4450         label3 = newiTempLabel(NULL);
4451
4452         /* the following algorithm is extracted from divuint.c */
4453
4454         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4455         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4456         
4457         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4458
4459         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4460         
4461         pic16_emitpLabel(label1->key);
4462         
4463         emitCLRC;
4464         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4465
4466
4467         emitCLRC;
4468         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4469         
4470
4471         emitSKPNC;
4472         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4473         
4474         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4475         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4476         
4477         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4478         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4479         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4480         
4481         pic16_emitpLabel( label3->key );
4482         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4483         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4484         
4485         
4486
4487         pic16_emitpLabel(label2->key);
4488         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4489         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4490         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4491         
4492         /* result is in wreg */
4493         if(AOP_TYPE(result) != AOP_ACC)
4494                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4495
4496         pic16_popReleaseTempReg( pct3, 1);
4497         pic16_popReleaseTempReg( pct2, 1);
4498         pic16_popReleaseTempReg( pct1, 1);
4499
4500         return ;
4501     }
4502
4503     /* signed is a little bit more difficult */
4504
4505     /* save the signs of the operands */
4506     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4507     MOVA(l);    
4508     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4509     pic16_emitcode("push","acc"); /* save it on the stack */
4510
4511     /* now sign adjust for both left & right */
4512     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4513     MOVA(l);       
4514     lbl = newiTempLabel(NULL);
4515     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4516     pic16_emitcode("cpl","a");   
4517     pic16_emitcode("inc","a");
4518     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4519     pic16_emitcode("mov","b,a");
4520
4521     /* sign adjust left side */
4522     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4523     MOVA(l);
4524
4525     lbl = newiTempLabel(NULL);
4526     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4527     pic16_emitcode("cpl","a");
4528     pic16_emitcode("inc","a");
4529     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4530
4531     /* now the division */
4532     pic16_emitcode("div","ab");
4533     /* we are interested in the lower order
4534     only */
4535     pic16_emitcode("mov","b,a");
4536     lbl = newiTempLabel(NULL);
4537     pic16_emitcode("pop","acc");   
4538     /* if there was an over flow we don't 
4539     adjust the sign of the result */
4540     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4541     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4542     CLRC;
4543     pic16_emitcode("clr","a");
4544     pic16_emitcode("subb","a,b");
4545     pic16_emitcode("mov","b,a");
4546     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4547
4548     /* now we are done */
4549     pic16_aopPut(AOP(result),"b",0);
4550     if(size > 0){
4551         pic16_emitcode("mov","c,b.7");
4552         pic16_emitcode("subb","a,acc");   
4553     }
4554     while (size--)
4555         pic16_aopPut(AOP(result),"a",offset++);
4556
4557 }
4558 #endif
4559
4560 /*-----------------------------------------------------------------*/
4561 /* genDiv - generates code for division                            */
4562 /*-----------------------------------------------------------------*/
4563 static void genDiv (iCode *ic)
4564 {
4565     operand *left = IC_LEFT(ic);
4566     operand *right = IC_RIGHT(ic);
4567     operand *result= IC_RESULT(ic);   
4568     int negated = 0;
4569     int leftVal = 0, rightVal = 0;
4570     int signedLits = 0;
4571     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4572     int op = 0;
4573     
4574         /* Division is a very lengthy algorithm, so it is better
4575          * to call support routines than inlining algorithm.
4576          * Division functions written here just in case someone
4577          * wants to inline and not use the support libraries -- VR */
4578
4579     FENTRY;
4580     
4581     /* assign the amsops */
4582     pic16_aopOp (left,ic,FALSE);
4583     pic16_aopOp (right,ic,FALSE);
4584     pic16_aopOp (result,ic,TRUE);
4585
4586     if (ic->op == '/')
4587       op = 0;
4588     else if (ic->op == '%')
4589       op = 1;
4590     else
4591       assert( !"invalid operation requested in genDivMod" );
4592
4593     /* get literal values */
4594     if (IS_VALOP(left)) {
4595       leftVal = (int)floatFromVal( OP_VALUE(left) );
4596       assert( leftVal >= -128 && leftVal < 256 );
4597       if (leftVal < 0) { signedLits++; }
4598     }
4599     if (IS_VALOP(right)) {
4600       rightVal = (int)floatFromVal( OP_VALUE(right) );
4601       assert( rightVal >= -128 && rightVal < 256 );
4602       if (rightVal < 0) { signedLits++; }
4603     }
4604
4605     /* We should only come here to convert all
4606      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4607      * with exactly one operand being s8_t into
4608      * u8_t x u8_t -> u8_t. All other cases should have been
4609      * turned into calls to support routines beforehand... */
4610     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4611         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4612     {
4613       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4614           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4615       {
4616         /* Both operands are signed or negative, use _divschar
4617          * instead of _divuchar */
4618         pushaop(AOP(right), 0);
4619         pushaop(AOP(left), 0);
4620
4621         /* call _divschar */
4622         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4623
4624         {
4625           symbol *sym;
4626           sym = newSymbol( functions[op][0], 0 );
4627           sym->used++;
4628           strcpy(sym->rname, functions[op][0]);
4629           checkAddSym(&externs, sym);
4630         }
4631
4632         /* assign result */
4633         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4634         if (AOP_SIZE(result) > 1)
4635         {
4636           pic16_emitpcode(POC_MOVFF,
4637               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4638                 pic16_popGet(AOP(result), 1)));
4639           /* sign extend */
4640           pic16_addSign(result, 2, 1);
4641         }
4642
4643         /* clean up stack */
4644         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4645         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4646
4647         goto release;
4648       }
4649       
4650       /* push right operand */
4651       if (IS_VALOP(right)) {
4652         if (rightVal < 0) {
4653           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4654           negated++;
4655         } else {
4656           pushaop(AOP(right), 0);
4657         }
4658       } else if (!IS_UNSIGNED(operandType(right))) {
4659         pic16_mov2w(AOP(right), 0);
4660         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4661         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4662         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4663         negated++;
4664       } else {
4665         pushaop(AOP(right), 0);
4666       }
4667
4668       /* push left operand */
4669       if (IS_VALOP(left)) {
4670         if (leftVal < 0) {
4671           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4672           negated++;
4673         } else {
4674           pushaop(AOP(left), 0);
4675         }
4676       } else if (!IS_UNSIGNED(operandType(left))) {
4677         pic16_mov2w(AOP(left),0);
4678         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4679         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4680         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4681         negated++;
4682       } else {
4683         pushaop(AOP(left), 0);
4684       }
4685       
4686       /* call _divuchar */
4687       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4688
4689       {
4690         symbol *sym;
4691         sym = newSymbol( functions[op][1], 0 );
4692         sym->used++;
4693         strcpy(sym->rname, functions[op][1]);
4694         checkAddSym(&externs, sym);
4695       }
4696
4697       /* Revert negation(s) from above.
4698        * This is inefficient: if both operands are negative, this
4699        * should not touch WREG. However, determining that exactly
4700        * one operand was negated costs at least 3 instructions,
4701        * so there is nothing to be gained here, is there?
4702        *
4703        * I negate WREG because either operand might share registers with
4704        * result, so assigning first might destroy an operand. */
4705       
4706       /* For the modulus operator, (a/b)*b == a shall hold.
4707        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4708        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
4709        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
4710        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
4711        * Only invert the result if the left operand is negative (sigh).
4712        */
4713       if (AOP_SIZE(result) <= 1 || !negated)
4714       {
4715         if (ic->op == '/')
4716         {
4717           if (IS_VALOP(right)) {
4718             if (rightVal < 0) {
4719               /* we negated this operand above */
4720               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4721             }
4722           } else if (!IS_UNSIGNED(operandType(right))) {
4723             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4724             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4725           }
4726         }
4727
4728         if (IS_VALOP(left)) {
4729           if (leftVal < 0) {
4730             /* we negated this operand above */
4731             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4732           }
4733         } else if (!IS_UNSIGNED(operandType(left))) {
4734           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4735           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4736         }
4737
4738         /* Move result to destination. */
4739         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4740
4741         /* Zero-extend:  no operand was signed (or result is just a byte). */
4742         pic16_addSign(result, 1, 0);
4743       } else {
4744         assert( AOP_SIZE(result) > 1 );
4745         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4746         if (ic->op == '/')
4747         {
4748           if (IS_VALOP(right)) {
4749             if (rightVal < 0) {
4750               /* we negated this operand above */
4751               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4752             }
4753           } else if (!IS_UNSIGNED(operandType(right))) {
4754             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4755             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4756           }
4757         }
4758
4759         if (IS_VALOP(left)) {
4760           if (leftVal < 0) {
4761             /* we negated this operand above */
4762             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4763           }
4764         } else if (!IS_UNSIGNED(operandType(left))) {
4765           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4766           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4767         }
4768
4769         /* Move result to destination. */
4770         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4771
4772         /* Negate result if required. */
4773         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4774         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4775
4776         /* Sign-extend. */
4777         pic16_addSign(result, 2, 1);
4778       }
4779
4780       /* clean up stack */
4781       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4782       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4783       goto release;
4784     }
4785
4786 #if 0
4787     /* special cases first */
4788     /* both are bits */
4789     if (AOP_TYPE(left) == AOP_CRY &&
4790         AOP_TYPE(right)== AOP_CRY) {
4791         genDivbits(left,right,result);
4792         goto release ;
4793     }
4794
4795     /* if both are of size == 1 */
4796     if (AOP_SIZE(left) == 1 &&
4797         AOP_SIZE(right) == 1 ) {
4798         genDivOneByte(left,right,result);
4799         goto release ;
4800     }
4801 #endif
4802
4803     /* should have been converted to function call */
4804     assert(0);
4805 release :
4806     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4807     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4808     pic16_freeAsmop(result,NULL,ic,TRUE); 
4809 }
4810
4811 #if 0
4812 /*-----------------------------------------------------------------*/
4813 /* genModbits :- modulus of bits                                   */
4814 /*-----------------------------------------------------------------*/
4815 static void genModbits (operand *left, 
4816                         operand *right, 
4817                         operand *result)
4818 {
4819   char *l;
4820
4821     FENTRY;  
4822     
4823     werror(W_POSSBUG2, __FILE__, __LINE__);
4824     /* the result must be bit */    
4825     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4826     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4827
4828     MOVA(l);       
4829
4830     pic16_emitcode("div","ab");
4831     pic16_emitcode("mov","a,b");
4832     pic16_emitcode("rrc","a");
4833     pic16_aopPut(AOP(result),"c",0);
4834 }
4835
4836 /*-----------------------------------------------------------------*/
4837 /* genModOneByte : 8 bit modulus                                   */
4838 /*-----------------------------------------------------------------*/
4839 static void genModOneByte (operand *left,
4840                            operand *right,
4841                            operand *result)
4842 {
4843   sym_link *opetype = operandType(result);
4844   char *l ;
4845   symbol *lbl ;
4846
4847     FENTRY;
4848     werror(W_POSSBUG2, __FILE__, __LINE__);
4849
4850     /* signed or unsigned */
4851     if (SPEC_USIGN(opetype)) {
4852         /* unsigned is easy */
4853         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4854         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4855         MOVA(l);    
4856         pic16_emitcode("div","ab");
4857         pic16_aopPut(AOP(result),"b",0);
4858         return ;
4859     }
4860
4861     /* signed is a little bit more difficult */
4862
4863     /* save the signs of the operands */
4864     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4865     MOVA(l);
4866
4867     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4868     pic16_emitcode("push","acc"); /* save it on the stack */
4869
4870     /* now sign adjust for both left & right */
4871     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4872     MOVA(l);
4873
4874     lbl = newiTempLabel(NULL);
4875     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4876     pic16_emitcode("cpl","a");   
4877     pic16_emitcode("inc","a");
4878     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4879     pic16_emitcode("mov","b,a"); 
4880
4881     /* sign adjust left side */
4882     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4883     MOVA(l);
4884
4885     lbl = newiTempLabel(NULL);
4886     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4887     pic16_emitcode("cpl","a");   
4888     pic16_emitcode("inc","a");
4889     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4890
4891     /* now the multiplication */
4892     pic16_emitcode("div","ab");
4893     /* we are interested in the lower order
4894     only */
4895     lbl = newiTempLabel(NULL);
4896     pic16_emitcode("pop","acc");   
4897     /* if there was an over flow we don't 
4898     adjust the sign of the result */
4899     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4900     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4901     CLRC ;
4902     pic16_emitcode("clr","a");
4903     pic16_emitcode("subb","a,b");
4904     pic16_emitcode("mov","b,a");
4905     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4906
4907     /* now we are done */
4908     pic16_aopPut(AOP(result),"b",0);
4909
4910 }
4911 #endif
4912
4913 /*-----------------------------------------------------------------*/
4914 /* genMod - generates code for division                            */
4915 /*-----------------------------------------------------------------*/
4916 static void genMod (iCode *ic)
4917 {
4918   /* Task deferred to genDiv */
4919   genDiv(ic);
4920 #if 0
4921   operand *left = IC_LEFT(ic);
4922   operand *right = IC_RIGHT(ic);
4923   operand *result= IC_RESULT(ic);  
4924
4925     FENTRY;
4926     
4927     /* assign the amsops */
4928     pic16_aopOp (left,ic,FALSE);
4929     pic16_aopOp (right,ic,FALSE);
4930     pic16_aopOp (result,ic,TRUE);
4931
4932     /* special cases first */
4933     /* both are bits */
4934     if (AOP_TYPE(left) == AOP_CRY &&
4935         AOP_TYPE(right)== AOP_CRY) {
4936         genModbits(left,right,result);
4937         goto release ;
4938     }
4939
4940     /* if both are of size == 1 */
4941     if (AOP_SIZE(left) == 1 &&
4942         AOP_SIZE(right) == 1 ) {
4943         genModOneByte(left,right,result);
4944         goto release ;
4945     }
4946
4947     /* should have been converted to function call */
4948     assert(0);
4949
4950 release :
4951     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4952     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4953     pic16_freeAsmop(result,NULL,ic,TRUE); 
4954 #endif
4955 }
4956
4957 /*-----------------------------------------------------------------*/
4958 /* genIfxJump :- will create a jump depending on the ifx           */
4959 /*-----------------------------------------------------------------*/
4960 /*
4961   note: May need to add parameter to indicate when a variable is in bit space.
4962 */
4963 static void genIfxJump (iCode *ic, char *jval)
4964 {
4965   FENTRY;
4966   
4967     /* if true label then we jump if condition
4968     supplied is true */
4969     if ( IC_TRUE(ic) ) {
4970
4971         if(strcmp(jval,"a") == 0)
4972           emitSKPZ;
4973         else if (strcmp(jval,"c") == 0)
4974           emitSKPNC;
4975         else {
4976           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4977           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4978         }
4979
4980         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4981         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4982
4983     }
4984     else {
4985         /* false label is present */
4986         if(strcmp(jval,"a") == 0)
4987           emitSKPNZ;
4988         else if (strcmp(jval,"c") == 0)
4989           emitSKPC;
4990         else {
4991           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4992           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4993         }
4994
4995         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4996         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4997
4998     }
4999
5000
5001     /* mark the icode as generated */
5002     ic->generated = 1;
5003 }
5004
5005 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5006 {
5007   FENTRY;
5008   
5009     /* if true label then we jump if condition
5010     supplied is true */
5011     if ( IC_TRUE(ic) ) {
5012       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
5013       pic16_emitpcode(POC_BTFSC, jop);
5014
5015       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5016       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5017
5018     } else {
5019       /* false label is present */
5020       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5021       pic16_emitpcode(POC_BTFSS, jop);
5022           
5023       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5024       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5025     }
5026
5027
5028     /* mark the icode as generated */
5029     ic->generated = 1;
5030 }
5031
5032 #if 0
5033 // not needed ATM
5034
5035 /*-----------------------------------------------------------------*/
5036 /* genSkip                                                         */
5037 /*-----------------------------------------------------------------*/
5038 static void genSkip(iCode *ifx,int status_bit)
5039 {
5040   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5041   if(!ifx)
5042     return;
5043
5044   if ( IC_TRUE(ifx) ) {
5045     switch(status_bit) {
5046     case 'z':
5047       emitSKPNZ;
5048       break;
5049
5050     case 'c':
5051       emitSKPNC;
5052       break;
5053
5054     case 'd':
5055       emitSKPDC;
5056       break;
5057
5058     }
5059
5060     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5061     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5062
5063   } else {
5064
5065     switch(status_bit) {
5066
5067     case 'z':
5068       emitSKPZ;
5069       break;
5070
5071     case 'c':
5072       emitSKPC;
5073       break;
5074
5075     case 'd':
5076       emitSKPDC;
5077       break;
5078     }
5079     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5080     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5081
5082   }
5083
5084 }
5085 #endif
5086
5087 /*-----------------------------------------------------------------*/
5088 /* genSkipc                                                        */
5089 /*-----------------------------------------------------------------*/
5090 static void genSkipc(resolvedIfx *rifx)
5091 {
5092   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5093   
5094   if(!rifx)
5095     return;
5096
5097   if(rifx->condition)
5098     emitSKPNC;
5099   else
5100     emitSKPC;
5101
5102   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5103   rifx->generated = 1;
5104 }
5105
5106 #if !(USE_SIMPLE_GENCMP)
5107 /*-----------------------------------------------------------------*/
5108 /* genSkipz2                                                       */
5109 /*-----------------------------------------------------------------*/
5110 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5111 {
5112   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5113   
5114   if(!rifx)
5115     return;
5116
5117   if( (rifx->condition ^ invert_condition) & 1)
5118     emitSKPZ;
5119   else
5120     emitSKPNZ;
5121
5122   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5123   rifx->generated = 1;
5124 }
5125 #endif
5126
5127 #if 0
5128 /*-----------------------------------------------------------------*/
5129 /* genSkipz                                                        */
5130 /*-----------------------------------------------------------------*/
5131 static void genSkipz(iCode *ifx, int condition)
5132 {
5133   if(!ifx)
5134     return;
5135
5136   if(condition)
5137     emitSKPNZ;
5138   else
5139     emitSKPZ;
5140
5141   if ( IC_TRUE(ifx) )
5142     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5143   else
5144     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5145
5146   if ( IC_TRUE(ifx) )
5147     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5148   else
5149     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5150
5151 }
5152 #endif
5153
5154 #if !(USE_SIMPLE_GENCMP)
5155 /*-----------------------------------------------------------------*/
5156 /* genSkipCond                                                     */
5157 /*-----------------------------------------------------------------*/
5158 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5159 {
5160   if(!rifx)
5161     return;
5162
5163   if(rifx->condition)
5164     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5165   else
5166     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5167
5168
5169   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5170   rifx->generated = 1;
5171 }
5172 #endif
5173
5174 #if 0
5175 /*-----------------------------------------------------------------*/
5176 /* genChkZeroes :- greater or less than comparison                 */
5177 /*     For each byte in a literal that is zero, inclusive or the   */
5178 /*     the corresponding byte in the operand with W                */
5179 /*     returns true if any of the bytes are zero                   */
5180 /*-----------------------------------------------------------------*/
5181 static int genChkZeroes(operand *op, int lit,  int size)
5182 {
5183
5184   int i;
5185   int flag =1;
5186
5187   while(size--) {
5188     i = (lit >> (size*8)) & 0xff;
5189
5190     if(i==0) {
5191       if(flag) 
5192         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5193       else
5194         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5195       flag = 0;
5196     }
5197   }
5198
5199   return (flag==0);
5200 }
5201 #endif
5202
5203
5204 /*-----------------------------------------------------------------*/
5205 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
5206 /*                  aop (if it's NOT a literal) or from lit (if    */
5207 /*                  aop is a literal)                              */
5208 /*-----------------------------------------------------------------*/
5209 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5210   if (aop->type == AOP_LIT) {
5211     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5212   } else {
5213     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5214   }
5215 }
5216
5217 /*-----------------------------------------------------------------*/
5218 /* genCmp :- greater or less than comparison                       */
5219 /*-----------------------------------------------------------------*/
5220
5221 #if USE_SIMPLE_GENCMP           /* { */
5222
5223 /* genCmp performs a left < right comparison, stores
5224  * the outcome in result (if != NULL) and generates
5225  * control flow code for the ifx (if != NULL).
5226  *
5227  * This version leaves in sequences like
5228  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5229  * which should be optmized by the peephole
5230  * optimizer - RN 2005-01-01 */
5231 static void genCmp (operand *left,operand *right,
5232                     operand *result, iCode *ifx, int sign)
5233 {
5234   resolvedIfx rIfx;
5235   int size;
5236   int offs;
5237   symbol *templbl;
5238   operand *dummy;
5239   unsigned long lit;
5240   unsigned long mask;
5241   int performedLt;
5242
5243   FENTRY;
5244   
5245   assert (left && right);
5246   assert (AOP_SIZE(left) == AOP_SIZE(right));
5247
5248   size = AOP_SIZE(right) - 1;
5249   mask = (0x100UL << (size*8)) - 1;
5250   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5251   performedLt = 1;
5252   templbl = NULL;
5253   lit = 0;
5254   
5255   resolveIfx (&rIfx, ifx);
5256
5257   /* handle for special cases */
5258   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5259       return;
5260
5261   /**********************************************************************
5262    * handle bits - bit compares are promoted to int compares seemingly! *
5263    **********************************************************************/
5264 #if 0
5265   // THIS IS COMPLETELY UNTESTED!
5266   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5267     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5268     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5269     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5270
5271     emitSETC;
5272     // 1 < {0,1} is false --> clear C by skipping the next instruction
5273     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5274     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5275     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5276     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5277     emitCLRC; // only skipped for left=0 && right=1
5278
5279     goto correct_result_in_carry;
5280   } // if
5281 #endif
5282
5283   /*************************************************
5284    * make sure that left is register (or the like) *
5285    *************************************************/
5286   if (!isAOP_REGlike(left)) {
5287     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5288     assert (isAOP_LIT(left));
5289     assert (isAOP_REGlike(right));
5290     // swap left and right
5291     // left < right <==> right > left <==> (right >= left + 1)
5292     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5293
5294     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5295       // MAXVALUE < right? always false
5296       if (performedLt) emitCLRC; else emitSETC;
5297       goto correct_result_in_carry;
5298     } // if
5299
5300     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5301     // that's why we handled it above.
5302     lit++;
5303
5304     dummy = left;
5305     left = right;
5306     right = dummy;
5307
5308     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5309   } else if (isAOP_LIT(right)) {
5310     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5311   } // if
5312
5313   assert (isAOP_REGlike(left)); // left must be register or the like
5314   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5315
5316   /*************************************************
5317    * special cases go here                         *
5318    *************************************************/
5319
5320   if (isAOP_LIT(right)) {
5321     if (!sign) {
5322       // unsigned comparison to a literal
5323       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5324       if (lit == 0) {
5325         // unsigned left < 0? always false
5326         if (performedLt) emitCLRC; else emitSETC;
5327         goto correct_result_in_carry;
5328       }
5329     } else {
5330       // signed comparison to a literal
5331       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5332       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5333         // signed left < 0x80000000? always false
5334         if (performedLt) emitCLRC; else emitSETC;
5335         goto correct_result_in_carry;
5336       } else if (lit == 0) {
5337         // compare left < 0; set CARRY if SIGNBIT(left) is set
5338         if (performedLt) emitSETC; else emitCLRC;
5339         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5340         if (performedLt) emitCLRC; else emitSETC;
5341         goto correct_result_in_carry;
5342       }
5343     } // if (!sign)
5344   } // right is literal
5345
5346   /*************************************************
5347    * perform a general case comparison             *
5348    * make sure we get CARRY==1 <==> left >= right  *
5349    *************************************************/
5350   // compare most significant bytes
5351   //DEBUGpc ("comparing bytes at offset %d", size);
5352   if (!sign) {
5353     // unsigned comparison
5354     mov2w_regOrLit (AOP(right), lit, size);
5355     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5356   } else {
5357     // signed comparison
5358     // (add 2^n to both operands then perform an unsigned comparison)
5359     if (isAOP_LIT(right)) {
5360       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5361       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5362
5363       if (litbyte == 0x80) {
5364         // left >= 0x80 -- always true, but more bytes to come
5365         pic16_mov2w (AOP(left), size);
5366         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5367         emitSETC;
5368       } else {
5369         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5370         pic16_mov2w (AOP(left), size);
5371         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5372         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5373       } // if
5374     } else {
5375       /* using PRODL as a temporary register here */
5376       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5377       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5378       pic16_mov2w (AOP(left), size);
5379       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5380       pic16_emitpcode (POC_MOVWF, pctemp);
5381       pic16_mov2w (AOP(right), size);
5382       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5383       pic16_emitpcode (POC_SUBFW, pctemp);
5384       //pic16_popReleaseTempReg(pctemp, 1);
5385     }
5386   } // if (!sign)
5387
5388   // compare remaining bytes (treat as unsigned case from above)
5389   templbl = newiTempLabel ( NULL );
5390   offs = size;
5391   while (offs--) {
5392     //DEBUGpc ("comparing bytes at offset %d", offs);
5393     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5394     mov2w_regOrLit (AOP(right), lit, offs);
5395     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5396   } // while (offs)
5397   pic16_emitpLabel (templbl->key);
5398   goto result_in_carry;
5399
5400 result_in_carry:
5401   
5402   /****************************************************
5403    * now CARRY contains the result of the comparison: *
5404    * SUBWF sets CARRY iff                             *
5405    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5406    * (F=left, W=right)                                *
5407    ****************************************************/
5408
5409   if (performedLt) {
5410     if (result && AOP_TYPE(result) != AOP_CRY) {
5411       // value will be stored
5412       emitTOGC;
5413     } else {
5414       // value wil only be used in the following genSkipc()
5415       rIfx.condition ^= 1;
5416     }
5417   } // if
5418
5419 correct_result_in_carry:
5420
5421   // assign result to variable (if neccessary)
5422   if (result && AOP_TYPE(result) != AOP_CRY) {
5423     //DEBUGpc ("assign result");
5424     size = AOP_SIZE(result);
5425     while (size--) {
5426       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5427     } // while
5428     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5429   } // if (result)
5430
5431   // perform conditional jump
5432   if (ifx) {
5433     //DEBUGpc ("generate control flow");
5434     genSkipc (&rIfx);
5435     ifx->generated = 1;
5436   } // if
5437 }
5438
5439 #elif 1         /* } */
5440                 /* { */
5441       /* original code */
5442 static void genCmp (operand *left,operand *right,
5443                     operand *result, iCode *ifx, int sign)
5444 {
5445   int size; //, offset = 0 ;
5446   unsigned long lit = 0L,i = 0;
5447   resolvedIfx rFalseIfx;
5448   //  resolvedIfx rTrueIfx;
5449   symbol *truelbl;
5450   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5451 /*
5452   if(ifx) {
5453     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5454     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5455   }
5456 */
5457
5458   FENTRY;
5459   
5460   resolveIfx(&rFalseIfx,ifx);
5461   truelbl  = newiTempLabel(NULL);
5462   size = max(AOP_SIZE(left),AOP_SIZE(right));
5463
5464   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5465
5466 #define _swapp
5467
5468   /* if literal is on the right then swap with left */
5469   if ((AOP_TYPE(right) == AOP_LIT)) {
5470     operand *tmp = right ;
5471     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5472     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5473 #ifdef _swapp
5474
5475     lit = (lit - 1) & mask;
5476     right = left;
5477     left = tmp;
5478     rFalseIfx.condition ^= 1;
5479 #endif
5480
5481   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5482     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5483   }
5484
5485
5486   //if(IC_TRUE(ifx) == NULL)
5487   /* if left & right are bit variables */
5488   if (AOP_TYPE(left) == AOP_CRY &&
5489       AOP_TYPE(right) == AOP_CRY ) {
5490     assert (0 && "bit variables used in genCmp");
5491     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5492     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5493   } else {
5494     /* subtract right from left if at the
5495        end the carry flag is set then we know that
5496        left is greater than right */
5497
5498     symbol *lbl  = newiTempLabel(NULL);
5499
5500 #if 0
5501         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5502                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5503 #endif
5504
5505 #ifndef _swapp
5506     if(AOP_TYPE(right) == AOP_LIT) {
5507
5508       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5509
5510       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5511
5512       /* special cases */
5513
5514       if(lit == 0) {
5515
5516         if(sign != 0) 
5517           genSkipCond(&rFalseIfx,left,size-1,7);
5518         else 
5519           /* no need to compare to 0...*/
5520           /* NOTE: this is a de-generate compare that most certainly 
5521            *       creates some dead code. */
5522           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5523
5524         if(ifx) ifx->generated = 1;
5525         return;
5526
5527       }
5528       size--;
5529
5530       if(size == 0) {
5531         //i = (lit >> (size*8)) & 0xff;
5532         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5533         
5534         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5535
5536         i = ((0-lit) & 0xff);
5537         if(sign) {
5538           if( i == 0x81) { 
5539             /* lit is 0x7f, all signed chars are less than
5540              * this except for 0x7f itself */
5541             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5542             genSkipz2(&rFalseIfx,0);
5543           } else {
5544             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5545             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5546             genSkipc(&rFalseIfx);
5547           }
5548
5549         } else {
5550           if(lit == 1) {
5551             genSkipz2(&rFalseIfx,1);
5552           } else {
5553             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5554             genSkipc(&rFalseIfx);
5555           }
5556         }
5557
5558         if(ifx) ifx->generated = 1;
5559         return;
5560       }
5561
5562       /* chars are out of the way. now do ints and longs */
5563
5564
5565       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5566         
5567       /* special cases */
5568
5569       if(sign) {
5570
5571         if(lit == 0) {
5572           genSkipCond(&rFalseIfx,left,size,7);
5573           if(ifx) ifx->generated = 1;
5574           return;
5575         }
5576
5577         if(lit <0x100) {
5578           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5579
5580           //rFalseIfx.condition ^= 1;
5581           //genSkipCond(&rFalseIfx,left,size,7);
5582           //rFalseIfx.condition ^= 1;
5583
5584           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5585           if(rFalseIfx.condition)
5586             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5587           else
5588             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5589
5590           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5591           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5592           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5593
5594           while(size > 1)
5595             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5596
5597           if(rFalseIfx.condition) {
5598             emitSKPZ;
5599             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5600
5601           } else {
5602             emitSKPNZ;
5603           }
5604
5605           genSkipc(&rFalseIfx);
5606           pic16_emitpLabel(truelbl->key);
5607           if(ifx) ifx->generated = 1;
5608           return;
5609
5610         }
5611
5612         if(size == 1) {
5613
5614           if( (lit & 0xff) == 0) {
5615             /* lower byte is zero */
5616             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5617             i = ((lit >> 8) & 0xff) ^0x80;
5618             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5619             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5620             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5621             genSkipc(&rFalseIfx);
5622
5623
5624             if(ifx) ifx->generated = 1;
5625             return;
5626
5627           }
5628         } else {
5629           /* Special cases for signed longs */
5630           if( (lit & 0xffffff) == 0) {
5631             /* lower byte is zero */
5632             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5633             i = ((lit >> 8*3) & 0xff) ^0x80;
5634             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5635             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5636             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5637             genSkipc(&rFalseIfx);
5638
5639
5640             if(ifx) ifx->generated = 1;
5641             return;
5642
5643           }
5644
5645         }
5646
5647
5648         if(lit & (0x80 << (size*8))) {
5649           /* lit is negative */
5650           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5651
5652           //genSkipCond(&rFalseIfx,left,size,7);
5653
5654           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5655
5656           if(rFalseIfx.condition)
5657             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5658           else
5659             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5660
5661
5662         } else {
5663           /* lit is positive */
5664           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5665           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5666           if(rFalseIfx.condition)
5667             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5668           else
5669             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5670
5671         }
5672
5673         /*
5674           This works, but is only good for ints.
5675           It also requires a "known zero" register.
5676           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5677           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5678           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5679           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5680           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5681           genSkipc(&rFalseIfx);
5682
5683           pic16_emitpLabel(truelbl->key);
5684           if(ifx) ifx->generated = 1;
5685           return;
5686         **/
5687           
5688         /* There are no more special cases, so perform a general compare */
5689   
5690         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5691         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5692
5693         while(size--) {
5694
5695           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5696           emitSKPNZ;
5697           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5698         }
5699         //rFalseIfx.condition ^= 1;
5700         genSkipc(&rFalseIfx);
5701
5702         pic16_emitpLabel(truelbl->key);
5703
5704         if(ifx) ifx->generated = 1;
5705         return;
5706
5707
5708       }
5709
5710
5711       /* sign is out of the way. So now do an unsigned compare */
5712       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5713
5714
5715       /* General case - compare to an unsigned literal on the right.*/
5716
5717       i = (lit >> (size*8)) & 0xff;
5718       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5719       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5720       while(size--) {
5721         i = (lit >> (size*8)) & 0xff;
5722
5723         if(i) {
5724           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5725           emitSKPNZ;
5726           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5727         } else {
5728           /* this byte of the lit is zero, 
5729            *if it's not the last then OR in the variable */
5730           if(size)
5731             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5732         }
5733       }
5734
5735
5736       pic16_emitpLabel(lbl->key);
5737 //      pic16_emitpLabel(truelbl->key);
5738       //if(emitFinalCheck)
5739       genSkipc(&rFalseIfx);
5740       if(sign)
5741         pic16_emitpLabel(truelbl->key);
5742
5743       if(ifx) ifx->generated = 1;
5744       return;
5745
5746
5747     }
5748 #endif  // _swapp
5749
5750     if(AOP_TYPE(left) == AOP_LIT) {
5751       //symbol *lbl = newiTempLabel(NULL);
5752
5753       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5754
5755
5756       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5757
5758       /* Special cases */
5759       if((lit == 0) && (sign == 0)){
5760
5761         size--;
5762         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5763         while(size) 
5764           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5765
5766         genSkipz2(&rFalseIfx,0);
5767         if(ifx) ifx->generated = 1;
5768         return;
5769       }
5770
5771       if(size==1) {
5772         /* Special cases */
5773         lit &= 0xff;
5774         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5775           /* degenerate compare can never be true */
5776           if(rFalseIfx.condition == 0)
5777             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5778
5779           if(ifx) ifx->generated = 1;
5780           return;
5781         }
5782
5783         if(sign) {
5784           /* signed comparisons to a literal byte */
5785
5786           int lp1 = (lit+1) & 0xff;
5787
5788           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5789           switch (lp1) {
5790           case 0:
5791             rFalseIfx.condition ^= 1;
5792             genSkipCond(&rFalseIfx,right,0,7);
5793             break;
5794           case 0x7f:
5795             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5796             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5797             genSkipz2(&rFalseIfx,1);
5798             break;
5799           default:
5800             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5801             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5802             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5803             rFalseIfx.condition ^= 1;
5804             genSkipc(&rFalseIfx);
5805             break;
5806           }
5807         } else {
5808           /* unsigned comparisons to a literal byte */
5809
5810           switch(lit & 0xff ) {
5811           case 0:
5812             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5813             genSkipz2(&rFalseIfx,0);
5814             break;
5815           case 0x7f:
5816             rFalseIfx.condition ^= 1;
5817             genSkipCond(&rFalseIfx,right,0,7);
5818             break;
5819
5820           default:
5821             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5822             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5823             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5824             rFalseIfx.condition ^= 1;
5825             if (AOP_TYPE(result) == AOP_CRY)
5826               genSkipc(&rFalseIfx);
5827             else {
5828               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5829               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5830             }         
5831             break;
5832           }
5833         }
5834
5835         if(ifx) ifx->generated = 1;
5836         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5837                 goto check_carry;
5838         return;
5839
5840       } else {
5841
5842         /* Size is greater than 1 */
5843
5844         if(sign) {
5845           int lp1 = lit+1;
5846
5847           size--;
5848
5849           if(lp1 == 0) {
5850             /* this means lit = 0xffffffff, or -1 */
5851
5852
5853             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5854             rFalseIfx.condition ^= 1;
5855             genSkipCond(&rFalseIfx,right,size,7);
5856             if(ifx) ifx->generated = 1;
5857
5858             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5859               goto check_carry;
5860
5861             return;
5862           }
5863
5864           if(lit == 0) {
5865             int s = size;
5866
5867             if(rFalseIfx.condition) {
5868               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5869               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5870             }
5871
5872             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5873             while(size--)
5874               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5875
5876
5877             emitSKPZ;
5878             if(rFalseIfx.condition) {
5879               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5880               pic16_emitpLabel(truelbl->key);
5881             }else {
5882               rFalseIfx.condition ^= 1;
5883               genSkipCond(&rFalseIfx,right,s,7);
5884             }
5885
5886             if(ifx) ifx->generated = 1;
5887
5888             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5889               goto check_carry;
5890
5891             return;
5892           }
5893
5894           if((size == 1) &&  (0 == (lp1&0xff))) {
5895             /* lower byte of signed word is zero */
5896             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5897             i = ((lp1 >> 8) & 0xff) ^0x80;
5898             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5899             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5900             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5901
5902             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5903               emitTOGC;
5904               if(ifx) ifx->generated = 1;
5905               goto check_carry;
5906             } else {
5907               rFalseIfx.condition ^= 1;
5908               genSkipc(&rFalseIfx);
5909               if(ifx) ifx->generated = 1;
5910             }
5911
5912             return;
5913           }
5914
5915           if(lit & (0x80 << (size*8))) {
5916             /* Lit is less than zero */
5917             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5918             //rFalseIfx.condition ^= 1;
5919             //genSkipCond(&rFalseIfx,left,size,7);
5920             //rFalseIfx.condition ^= 1;
5921             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5922             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5923
5924             if(rFalseIfx.condition)
5925               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5926             else
5927               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5928
5929
5930           } else {
5931             /* Lit is greater than or equal to zero */
5932             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5933             //rFalseIfx.condition ^= 1;
5934             //genSkipCond(&rFalseIfx,right,size,7);
5935             //rFalseIfx.condition ^= 1;
5936
5937             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5938             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5939
5940             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5941             if(rFalseIfx.condition)
5942               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5943             else
5944               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5945
5946           }
5947
5948           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5949           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5950
5951           while(size--) {
5952
5953             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5954             emitSKPNZ;
5955             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5956           }
5957           rFalseIfx.condition ^= 1;
5958           //rFalseIfx.condition = 1;
5959           genSkipc(&rFalseIfx);
5960
5961           pic16_emitpLabel(truelbl->key);
5962
5963           if(ifx) ifx->generated = 1;
5964
5965
5966           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5967             goto check_carry;
5968
5969           return;
5970           // end of if (sign)
5971         } else {
5972
5973           /* compare word or long to an unsigned literal on the right.*/
5974
5975
5976           size--;
5977           if(lit < 0xff) {
5978             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5979             switch (lit) {
5980             case 0:
5981               break; /* handled above */
5982 /*
5983             case 0xff:
5984               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5985               while(size--)
5986                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5987               genSkipz2(&rFalseIfx,0);
5988               break;
5989 */
5990             default:
5991               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5992               while(--size)
5993                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5994
5995               emitSKPZ;
5996               if(rFalseIfx.condition)
5997                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5998               else
5999                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6000
6001
6002               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6003               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6004
6005               rFalseIfx.condition ^= 1;
6006               genSkipc(&rFalseIfx);
6007             }
6008
6009             pic16_emitpLabel(truelbl->key);
6010
6011             if(ifx) ifx->generated = 1;
6012
6013             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6014               goto check_carry;
6015
6016             return;
6017           }
6018
6019
6020           lit++;
6021           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6022           i = (lit >> (size*8)) & 0xff;
6023
6024           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6025           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6026
6027           while(size--) {
6028             i = (lit >> (size*8)) & 0xff;
6029
6030             if(i) {
6031               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6032               emitSKPNZ;
6033               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6034             } else {
6035               /* this byte of the lit is zero, 
6036                * if it's not the last then OR in the variable */
6037               if(size)
6038                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6039             }
6040           }
6041
6042
6043           pic16_emitpLabel(lbl->key);
6044
6045           rFalseIfx.condition ^= 1;
6046
6047           genSkipc(&rFalseIfx);
6048         }
6049
6050         if(sign)
6051           pic16_emitpLabel(truelbl->key);
6052         if(ifx) ifx->generated = 1;
6053
6054             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6055               goto check_carry;
6056
6057         return;
6058       }
6059     }
6060     /* Compare two variables */
6061
6062     DEBUGpic16_emitcode(";sign","%d",sign);
6063
6064     size--;
6065     if(sign) {
6066       /* Sigh. thus sucks... */
6067       if(size) {
6068         pCodeOp *pctemp;
6069         
6070         pctemp = pic16_popGetTempReg(1);
6071         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6072         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6073         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6074         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6075         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6076         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6077         pic16_popReleaseTempReg(pctemp, 1);
6078       } else {
6079         /* Signed char comparison */
6080         /* Special thanks to Nikolai Golovchenko for this snippet */
6081         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6082         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6083         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6084         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6085         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6086         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6087
6088         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6089         genSkipc(&rFalseIfx);
6090           
6091         if(ifx) ifx->generated = 1;
6092
6093             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6094               goto check_carry;
6095
6096         return;
6097       }
6098
6099     } else {
6100
6101       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6102       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6103     }
6104
6105
6106     /* The rest of the bytes of a multi-byte compare */
6107     while (size) {
6108
6109       emitSKPZ;
6110       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6111       size--;
6112
6113       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6114       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6115
6116
6117     }
6118
6119     pic16_emitpLabel(lbl->key);
6120
6121     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6122     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6123         (AOP_TYPE(result) == AOP_REG)) {
6124       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6125       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6126     } else {
6127       genSkipc(&rFalseIfx);
6128     }         
6129     //genSkipc(&rFalseIfx);
6130     if(ifx) ifx->generated = 1;
6131
6132
6133             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6134               goto check_carry;
6135
6136     return;
6137
6138   }
6139
6140 check_carry:
6141   if ((AOP_TYPE(result) != AOP_CRY) 
6142         && AOP_SIZE(result)) {
6143     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6144
6145     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6146
6147     pic16_outBitC(result);
6148   } else {
6149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6150     /* if the result is used in the next
6151        ifx conditional branch then generate
6152        code a little differently */
6153     if (ifx )
6154       genIfxJump (ifx,"c");
6155     else
6156       pic16_outBitC(result);
6157     /* leave the result in acc */
6158   }
6159
6160 }
6161
6162 #elif 0 /* VR version of genCmp() */    /* } else { */
6163
6164 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6165 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6166         operand *result, int offset, int invert_op)
6167 {
6168   /* add code here */
6169   
6170   /* check condition, > or < ?? */
6171   if(rIfx->condition != 0)invert_op ^= 1;
6172   
6173   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6174
6175   if(!ifx)invert_op ^= 1;
6176
6177   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6178       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6179   
6180   /* do selection */
6181   if(!invert_op)return POC_CPFSGT;
6182   else return POC_CPFSLT;
6183 }
6184
6185 static int compareAopfirstpass=1;
6186
6187 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6188             operand *oper, int offset, operand *result,
6189             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6190             symbol *tlbl)
6191 {
6192   int op;
6193   symbol *truelbl;
6194
6195   /* invert if there is a result to be loaded, in order to fit,
6196    * SETC/CLRC sequence */
6197   if(AOP_SIZE(result))invert_op ^= 1;
6198
6199 //  if(sign && !offset)invert_op ^= 1;
6200   
6201 //  if(sign)invert_op ^= 1;
6202   
6203   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6204
6205   if(AOP_SIZE(result) && compareAopfirstpass) {
6206     if(!ifx) {
6207       if(pcop2)
6208         pic16_emitpcode(POC_SETF, pcop2);
6209       else
6210         emitSETC;
6211     } else {
6212       if(pcop2)
6213         pic16_emitpcode(POC_CLRF, pcop2);
6214       else
6215         emitCLRC;
6216     }
6217   }
6218
6219   compareAopfirstpass = 0;
6220
6221       /* there is a bug when comparing operands with size > 1,
6222        * because higher bytes can be equal and test should be performed
6223        * to the next lower byte, current algorithm, considers operands
6224        * inequal in these cases! -- VR 20041107 */
6225
6226     
6227   if(pcop)
6228     pic16_emitpcode(op, pcop);
6229   else
6230     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6231
6232
6233   if((!sign || !offset) && AOP_SIZE(result)) {
6234     if(!ifx) {
6235       if(pcop2)
6236         pic16_emitpcode(POC_CLRF, pcop2);
6237         else
6238         emitCLRC;
6239     } else {
6240       if(pcop2)
6241         pic16_emitpcode(POC_SETF, pcop2);
6242       else
6243         emitSETC;
6244     }
6245     
6246     /* don't emit final branch (offset == 0) */
6247     if(offset) {
6248
6249       if(pcop2)
6250         pic16_emitpcode(POC_RRCF, pcop2);
6251
6252       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6253     }
6254   } else {
6255     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6256       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6257             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6258
6259       truelbl = newiTempLabel( NULL );
6260       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6261       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6262         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6263       else
6264         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6265       pic16_emitpLabel(truelbl->key);
6266     } else {
6267       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6268     }
6269   }
6270 }
6271
6272 static void genCmp (operand *left, operand *right,
6273                     operand *result, iCode *ifx, int sign)
6274 {
6275   int size, cmpop=1;
6276   long lit = 0L;
6277   resolvedIfx rFalseIfx;
6278   symbol *falselbl, *tlbl;
6279
6280     FENTRY;
6281     
6282     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6283
6284     resolveIfx(&rFalseIfx, ifx);
6285     size = max(AOP_SIZE(left), AOP_SIZE(right));
6286     
6287     /* if left & right are bit variables */
6288     if(AOP_TYPE(left) == AOP_CRY
6289       && AOP_TYPE(right) == AOP_CRY ) {
6290
6291         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6292         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6293         
6294         werror(W_POSSBUG2, __FILE__, __LINE__);
6295         exit(EXIT_FAILURE);
6296     }
6297     
6298     /* if literal is on the right then swap with left */
6299     if((AOP_TYPE(right) == AOP_LIT)) {
6300       operand *tmp = right ;
6301 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6302
6303         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6304
6305 //      lit = (lit - 1) & mask;
6306         right = left;
6307         left = tmp;
6308         rFalseIfx.condition ^= 1;               /* reverse compare */
6309     } else
6310     if ((AOP_TYPE(left) == AOP_LIT)) {
6311       /* float compares are handled by support functions */
6312       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6313     }
6314
6315     /* actual comparing algorithm */
6316 //    size = AOP_SIZE( right );
6317
6318     falselbl = newiTempLabel( NULL );
6319     if(AOP_TYPE(left) == AOP_LIT) {
6320       /* compare to literal */
6321       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6322       
6323       if(sign) {
6324         pCodeOp *pct, *pct2;
6325         symbol *tlbl1;
6326
6327         /* signed compare */
6328         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6329
6330         /* using PRODL:PRODH as a temporary register here */
6331         pct = pic16_popCopyReg(&pic16_pc_prodl);
6332         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6333         tlbl = newiTempLabel( NULL );
6334         
6335         /* first compare signs:
6336          *  a. if both are positive, compare just like unsigned
6337          *  b. if both are negative, invert cmpop, compare just like unsigned
6338          *  c. if different signs, determine the result directly */
6339
6340         size--;
6341
6342 #if 1
6343         /* { */
6344         tlbl1 = newiTempLabel( NULL );
6345 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6346
6347         if(lit > 0) {
6348
6349           /* literal is zero or positive:
6350            *  a. if carry is zero, too, continue compare,
6351            *  b. if carry is set, then continue depending on cmpop ^ condition:
6352            *    1. '<' return false (literal < variable),
6353            *    2. '>' return true (literal > variable) */
6354 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6355           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6356           
6357           
6358           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6359           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6360         } else 
6361         if(lit < 0) {
6362           
6363           /* literal is negative:
6364            *  a. if carry is set, too, continue compare,
6365            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6366            *    1. '<' return true (literal < variable),
6367            *    2. '>' return false (literal > variable) */
6368 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6369           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6370           
6371           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6372           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6373         }
6374 #if 1
6375         else {
6376           /* lit == 0 */
6377           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6378           
6379           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6380           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6381         }
6382 #endif
6383         
6384         
6385         pic16_emitpLabel( tlbl1->key );
6386 #endif  /* } */
6387
6388         compareAopfirstpass=1;
6389 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6390 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6391 //        pic16_emitpcode(POC_MOVWF, pct);
6392
6393 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6394         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6395 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6396         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6397
6398         /* generic case */        
6399           while( size-- ) {
6400 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6401 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6402 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6403 //            pic16_emitpcode(POC_MOVWF, pct);
6404
6405 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6406             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6407             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6408 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6409 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6410           }
6411         
6412         if(ifx)ifx->generated = 1;
6413
6414         if(AOP_SIZE(result)) {
6415           pic16_emitpLabel(tlbl->key);
6416           pic16_emitpLabel(falselbl->key);
6417           pic16_outBitOp( result, pct2 );
6418         } else {
6419           pic16_emitpLabel(tlbl->key);
6420         }
6421       } else {
6422
6423         /* unsigned compare */      
6424         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6425     
6426         compareAopfirstpass=1;
6427         while(size--) {
6428           
6429           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6430           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6431
6432         }
6433         if(ifx)ifx->generated = 1;
6434
6435         if(AOP_SIZE(result)) {
6436           pic16_emitpLabel(falselbl->key);
6437           pic16_outBitC( result );
6438         }
6439
6440       }
6441     } else {
6442       /* compare registers */
6443       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6444
6445
6446       if(sign) {
6447         pCodeOp *pct, *pct2;
6448         
6449         /* signed compare */
6450         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6451
6452         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6453         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6454         tlbl = newiTempLabel( NULL );
6455         
6456         compareAopfirstpass=1;
6457
6458         size--;
6459         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6460 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6461         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6462         pic16_emitpcode(POC_MOVWF, pct);
6463
6464         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6465 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6466         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6467
6468         /* WREG already holds left + 0x80 */
6469         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6470         
6471         while( size-- ) {
6472           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6473 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6474           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6475           pic16_emitpcode(POC_MOVWF, pct);
6476                 
6477           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6478 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6479           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6480
6481           /* WREG already holds left + 0x80 */
6482           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6483 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6484         }
6485         
6486         if(ifx)ifx->generated = 1;
6487
6488         if(AOP_SIZE(result)) {
6489           pic16_emitpLabel(tlbl->key);
6490           pic16_emitpLabel(falselbl->key);
6491           pic16_outBitOp( result, pct2 );
6492         } else {
6493           pic16_emitpLabel(tlbl->key);
6494         }
6495
6496       } else {
6497         /* unsigned compare */      
6498         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6499
6500         compareAopfirstpass=1;
6501         while(size--) {
6502           
6503           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6504           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6505
6506         }
6507
6508         if(ifx)ifx->generated = 1;
6509         if(AOP_SIZE(result)) {
6510
6511           pic16_emitpLabel(falselbl->key);
6512           pic16_outBitC( result );
6513         }
6514
6515       }
6516     }
6517 }
6518
6519 #endif  /* } */
6520
6521
6522
6523 /*-----------------------------------------------------------------*/
6524 /* genCmpGt :- greater than comparison                             */
6525 /*-----------------------------------------------------------------*/
6526 static void genCmpGt (iCode *ic, iCode *ifx)
6527 {
6528   operand *left, *right, *result;
6529   sym_link *letype , *retype;
6530   int sign ;
6531
6532     FENTRY;
6533     
6534     left = IC_LEFT(ic);
6535     right= IC_RIGHT(ic);
6536     result = IC_RESULT(ic);
6537
6538     letype = getSpec(operandType(left));
6539     retype =getSpec(operandType(right));
6540     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6541     /* assign the amsops */
6542     pic16_aopOp (left,ic,FALSE);
6543     pic16_aopOp (right,ic,FALSE);
6544     pic16_aopOp (result,ic,TRUE);
6545
6546     genCmp(right, left, result, ifx, sign);
6547
6548     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6549     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6550     pic16_freeAsmop(result,NULL,ic,TRUE); 
6551 }
6552
6553 /*-----------------------------------------------------------------*/
6554 /* genCmpLt - less than comparisons                                */
6555 /*-----------------------------------------------------------------*/
6556 static void genCmpLt (iCode *ic, iCode *ifx)
6557 {
6558   operand *left, *right, *result;
6559   sym_link *letype , *retype;
6560   int sign ;
6561
6562     FENTRY;
6563
6564     left = IC_LEFT(ic);
6565     right= IC_RIGHT(ic);
6566     result = IC_RESULT(ic);
6567
6568     letype = getSpec(operandType(left));
6569     retype =getSpec(operandType(right));
6570     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6571
6572     /* assign the amsops */
6573     pic16_aopOp (left,ic,FALSE);
6574     pic16_aopOp (right,ic,FALSE);
6575     pic16_aopOp (result,ic,TRUE);
6576
6577     genCmp(left, right, result, ifx, sign);
6578
6579     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6581     pic16_freeAsmop(result,NULL,ic,TRUE); 
6582 }
6583
6584 #if 0
6585 // not needed ATM
6586 // FIXME reenable literal optimisation when the pic16 port is stable
6587
6588 /*-----------------------------------------------------------------*/
6589 /* genc16bit2lit - compare a 16 bit value to a literal             */
6590 /*-----------------------------------------------------------------*/
6591 static void genc16bit2lit(operand *op, int lit, int offset)
6592 {
6593   int i;
6594
6595   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6596   if( (lit&0xff) == 0) 
6597     i=1;
6598   else
6599     i=0;
6600
6601   switch( BYTEofLONG(lit,i)) { 
6602   case 0:
6603     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6604     break;
6605   case 1:
6606     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6607     break;
6608   case 0xff:
6609     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6610     break;
6611   default:
6612     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6613     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6614   }
6615
6616   i ^= 1;
6617
6618   switch( BYTEofLONG(lit,i)) { 
6619   case 0:
6620     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6621     break;
6622   case 1:
6623     emitSKPNZ;
6624     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6625     break;
6626   case 0xff:
6627     emitSKPNZ;
6628     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6629     break;
6630   default:
6631     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6632     emitSKPNZ;
6633     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6634
6635   }
6636
6637 }
6638 #endif
6639
6640 #if 0
6641 // not needed ATM
6642 /*-----------------------------------------------------------------*/
6643 /* gencjneshort - compare and jump if not equal                    */
6644 /*-----------------------------------------------------------------*/
6645 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6646 {
6647   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6648   int offset = 0;
6649   int res_offset = 0;  /* the result may be a different size then left or right */
6650   int res_size = AOP_SIZE(result);
6651   resolvedIfx rIfx;
6652   symbol *lbl, *lbl_done;
6653
6654   unsigned long lit = 0L;
6655   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6656
6657   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6658   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6659   if(result)
6660     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6661   resolveIfx(&rIfx,ifx);
6662   lbl =  newiTempLabel(NULL);
6663   lbl_done =  newiTempLabel(NULL);
6664
6665
6666   /* if the left side is a literal or 
6667      if the right is in a pointer register and left 
6668      is not */
6669   if ((AOP_TYPE(left) == AOP_LIT) || 
6670       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6671     operand *t = right;
6672     right = left;
6673     left = t;
6674   }
6675   if(AOP_TYPE(right) == AOP_LIT)
6676     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6677
6678   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6679     preserve_result = 1;
6680
6681   if(result && !preserve_result)
6682     {
6683       int i;
6684       for(i = 0; i < AOP_SIZE(result); i++)
6685         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6686     }
6687
6688
6689   /* if the right side is a literal then anything goes */
6690   if (AOP_TYPE(right) == AOP_LIT &&
6691       AOP_TYPE(left) != AOP_DIR ) {
6692     switch(size) {
6693     case 2:
6694       genc16bit2lit(left, lit, 0);
6695       emitSKPZ;
6696       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6697       break;
6698     default:
6699       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6700       while (size--) {
6701         if(lit & 0xff) {
6702           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6703           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6704         } else {
6705           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6706         }
6707
6708         emitSKPZ;
6709         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6710         offset++;
6711         if(res_offset < res_size-1)
6712           res_offset++;
6713         lit >>= 8;
6714       }
6715       break;
6716     }
6717   }
6718
6719   /* if the right side is in a register or in direct space or
6720      if the left is a pointer register & right is not */    
6721   else if (AOP_TYPE(right) == AOP_REG ||
6722            AOP_TYPE(right) == AOP_DIR || 
6723            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6724            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6725     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6726     int lbl_key = lbl->key;
6727
6728     if(result) {
6729       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6730       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6731     }else {
6732       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6733       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6734               __FUNCTION__,__LINE__);
6735       return;
6736     }
6737    
6738 /*     switch(size) { */
6739 /*     case 2: */
6740 /*       genc16bit2lit(left, lit, 0); */
6741 /*       emitSKPNZ; */
6742 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6743 /*       break; */
6744 /*     default: */
6745     while (size--) {
6746       int emit_skip=1;
6747       if((AOP_TYPE(left) == AOP_DIR) && 
6748          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6749
6750         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6751         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6752
6753       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6754             
6755         switch (lit & 0xff) {
6756         case 0:
6757           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6758           break;
6759         case 1:
6760           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6761           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6762           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6763           emit_skip=0;
6764           break;
6765         case 0xff:
6766           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6767           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6768           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6769           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6770           emit_skip=0;
6771           break;
6772         default:
6773           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6774           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6775         }
6776         lit >>= 8;
6777
6778       } else {
6779         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6780       }
6781       if(emit_skip) {
6782         if(AOP_TYPE(result) == AOP_CRY) {
6783           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6784           if(rIfx.condition)
6785             emitSKPNZ;
6786           else
6787             emitSKPZ;
6788           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6789         } else {
6790           /* fix me. probably need to check result size too */
6791           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6792           if(rIfx.condition)
6793             emitSKPZ;
6794           else
6795             emitSKPNZ;
6796           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6797           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6798         }
6799         if(ifx)
6800           ifx->generated=1;
6801       }
6802       emit_skip++;
6803       offset++;
6804       if(res_offset < res_size-1)
6805         res_offset++;
6806     }
6807 /*       break; */
6808 /*     } */
6809   } else if(AOP_TYPE(right) == AOP_REG &&
6810             AOP_TYPE(left) != AOP_DIR){
6811
6812     while(size--) {
6813       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6814       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6815       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6816       if(rIfx.condition)
6817         emitSKPNZ;
6818       else
6819         emitSKPZ;
6820       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6821       offset++;
6822       if(res_offset < res_size-1)
6823         res_offset++;
6824     }
6825       
6826   }else{
6827     /* right is a pointer reg need both a & b */
6828     while(size--) {
6829       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6830       if(strcmp(l,"b"))
6831         pic16_emitcode("mov","b,%s",l);
6832       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6833       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6834       offset++;
6835     }
6836   }
6837
6838   if(result && preserve_result)
6839     {
6840       int i;
6841       for(i = 0; i < AOP_SIZE(result); i++)
6842         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6843     }
6844
6845   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6846
6847   if(result && preserve_result)
6848     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6849
6850   if(!rIfx.condition)
6851     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6852
6853   pic16_emitpLabel(lbl->key);
6854
6855   if(result && preserve_result)
6856     {
6857       int i;
6858       for(i = 0; i < AOP_SIZE(result); i++)
6859         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6860
6861       pic16_emitpLabel(lbl_done->key);
6862    }
6863
6864   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6865
6866   if(ifx)
6867     ifx->generated = 1;
6868 }
6869 #endif
6870
6871 #if 0
6872 /*-----------------------------------------------------------------*/
6873 /* gencjne - compare and jump if not equal                         */
6874 /*-----------------------------------------------------------------*/
6875 static void gencjne(operand *left, operand *right, iCode *ifx)
6876 {
6877     symbol *tlbl  = newiTempLabel(NULL);
6878
6879     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6880     gencjneshort(left, right, lbl);
6881
6882     pic16_emitcode("mov","a,%s",one);
6883     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6884     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6885     pic16_emitcode("clr","a");
6886     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6887
6888     pic16_emitpLabel(lbl->key);
6889     pic16_emitpLabel(tlbl->key);
6890
6891 }
6892 #endif
6893
6894
6895 /*-----------------------------------------------------------------*/
6896 /* is_LitOp - check if operand has to be treated as literal        */
6897 /*-----------------------------------------------------------------*/
6898 static bool is_LitOp(operand *op)
6899 {
6900   return ((AOP_TYPE(op) == AOP_LIT)
6901       || ( (AOP_TYPE(op) == AOP_PCODE)
6902           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6903               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6904 }
6905
6906 /*-----------------------------------------------------------------*/
6907 /* is_LitAOp - check if operand has to be treated as literal        */
6908 /*-----------------------------------------------------------------*/
6909 static bool is_LitAOp(asmop *aop)
6910 {
6911   return ((aop->type == AOP_LIT)
6912       || ( (aop->type == AOP_PCODE)
6913           && ( (aop->aopu.pcop->type == PO_LITERAL)
6914               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6915 }
6916
6917
6918
6919 /*-----------------------------------------------------------------*/
6920 /* genCmpEq - generates code for equal to                          */
6921 /*-----------------------------------------------------------------*/
6922 static void genCmpEq (iCode *ic, iCode *ifx)
6923 {
6924   operand *left, *right, *result;
6925   symbol *falselbl = newiTempLabel(NULL);
6926   symbol *donelbl = newiTempLabel(NULL);
6927
6928   int preserve_result = 0;
6929   int generate_result = 0;
6930   int i=0;
6931   unsigned long lit = -1;
6932
6933   FENTRY;
6934   
6935   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6936   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6937   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6938  
6939   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6940
6941   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6942     {
6943       werror(W_POSSBUG2, __FILE__, __LINE__);
6944       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6945       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6946       goto release;
6947     }
6948
6949   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6950     {
6951       operand *tmp = right ;
6952       right = left;
6953       left = tmp;
6954     }
6955
6956   if (AOP_TYPE(right) == AOP_LIT) {
6957     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6958   }
6959
6960   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6961     preserve_result = 1;
6962
6963   if(result && AOP_SIZE(result))
6964     generate_result = 1;
6965
6966   if(generate_result && !preserve_result)
6967     {
6968       for(i = 0; i < AOP_SIZE(result); i++)
6969         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6970     }
6971
6972   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6973   for(i=0; i < AOP_SIZE(left); i++)
6974     {
6975       if(AOP_TYPE(left) != AOP_ACC)
6976         {
6977           if(is_LitOp(left))
6978             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6979           else
6980             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6981         }
6982       if(is_LitOp(right)) {
6983         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6984           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6985         }
6986       } else
6987         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6988
6989       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6990     }
6991
6992   // result == true
6993
6994   if(generate_result && preserve_result)
6995     {
6996       for(i = 0; i < AOP_SIZE(result); i++)
6997         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6998     }
6999
7000   if(generate_result)
7001     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7002
7003   if(generate_result && preserve_result)
7004     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7005
7006   if(ifx && IC_TRUE(ifx))
7007     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7008
7009   if(ifx && IC_FALSE(ifx))
7010     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7011
7012   pic16_emitpLabel(falselbl->key);
7013
7014   // result == false
7015
7016   if(ifx && IC_FALSE(ifx))
7017     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7018
7019   if(generate_result && preserve_result)
7020     {
7021       for(i = 0; i < AOP_SIZE(result); i++)
7022         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7023     }
7024
7025   pic16_emitpLabel(donelbl->key);
7026
7027   if(ifx)
7028     ifx->generated = 1;
7029
7030 release:
7031   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7032   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7033   pic16_freeAsmop(result,NULL,ic,TRUE);
7034
7035 }
7036
7037
7038 #if 0
7039 // old version kept for reference
7040
7041 /*-----------------------------------------------------------------*/
7042 /* genCmpEq - generates code for equal to                          */
7043 /*-----------------------------------------------------------------*/
7044 static void genCmpEq (iCode *ic, iCode *ifx)
7045 {
7046     operand *left, *right, *result;
7047     unsigned long lit = 0L;
7048     int size,offset=0;
7049     symbol *falselbl  = newiTempLabel(NULL);
7050
7051
7052     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7053
7054     if(ifx)
7055       DEBUGpic16_emitcode ("; ifx is non-null","");
7056     else
7057       DEBUGpic16_emitcode ("; ifx is null","");
7058
7059     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7060     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7061     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7062
7063     size = max(AOP_SIZE(left),AOP_SIZE(right));
7064
7065     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7066
7067     /* if literal, literal on the right or 
7068     if the right is in a pointer register and left 
7069     is not */
7070     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7071         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7072       operand *tmp = right ;
7073       right = left;
7074       left = tmp;
7075     }
7076
7077
7078     if(ifx && !AOP_SIZE(result)){
7079         symbol *tlbl;
7080         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7081         /* if they are both bit variables */
7082         if (AOP_TYPE(left) == AOP_CRY &&
7083             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7084                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7085             if(AOP_TYPE(right) == AOP_LIT){
7086                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7087                 if(lit == 0L){
7088                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7089                     pic16_emitcode("cpl","c");
7090                 } else if(lit == 1L) {
7091                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7092                 } else {
7093                     pic16_emitcode("clr","c");
7094                 }
7095                 /* AOP_TYPE(right) == AOP_CRY */
7096             } else {
7097                 symbol *lbl = newiTempLabel(NULL);
7098                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7099                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7100                 pic16_emitcode("cpl","c");
7101                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7102             }
7103             /* if true label then we jump if condition
7104             supplied is true */
7105             tlbl = newiTempLabel(NULL);
7106             if ( IC_TRUE(ifx) ) {
7107                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7108                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7109             } else {
7110                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7111                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7112             }
7113             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7114
7115                 {
7116                 /* left and right are both bit variables, result is carry */
7117                         resolvedIfx rIfx;
7118               
7119                         resolveIfx(&rIfx,ifx);
7120
7121                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7122                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7123                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7124                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7125                         genSkipz2(&rIfx,0);
7126                 }
7127         } else {
7128
7129                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7130
7131                         /* They're not both bit variables. Is the right a literal? */
7132                         if(AOP_TYPE(right) == AOP_LIT) {
7133                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7134             
7135                         switch(size) {
7136
7137                                 case 1:
7138                                         switch(lit & 0xff) {
7139                                                 case 1:
7140                                                                 if ( IC_TRUE(ifx) ) {
7141                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7142                                                                         emitSKPNZ;
7143                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7144                                                                 } else {
7145                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7146                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7147                                                                 }
7148                                                                 break;
7149                                                 case 0xff:
7150                                                                 if ( IC_TRUE(ifx) ) {
7151                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7152                                                                         emitSKPNZ;
7153                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7154                                                                 } else {
7155                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7156                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7157                                                                 }
7158                                                                 break;
7159                                                 default:
7160                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7161                                                                 if(lit)
7162                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7163                                                                 genSkip(ifx,'z');
7164                                         } // switch lit
7165
7166
7167                                         /* end of size == 1 */
7168                                         break;
7169               
7170                                 case 2:
7171                                         genc16bit2lit(left,lit,offset);
7172                                         genSkip(ifx,'z');
7173                                         break;
7174                                         /* end of size == 2 */
7175
7176                                 default:
7177                                         /* size is 4 */
7178                                         if(lit==0) {
7179                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7180                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7181                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7182                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7183                                                 genSkip(ifx,'z');
7184                                         } else {
7185                                                 /* search for patterns that can be optimized */
7186
7187                                                 genc16bit2lit(left,lit,0);
7188                                                 lit >>= 16;
7189                                                 if(lit) {
7190                                                                 if(IC_TRUE(ifx))
7191                                                                 emitSKPZ; // if hi word unequal
7192                                                                 else
7193                                                                 emitSKPNZ; // if hi word equal
7194                                                                 // fail early
7195                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7196                                                         genc16bit2lit(left,lit,2);
7197                                                         genSkip(ifx,'z');
7198                                                 } else {
7199                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7200                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7201                                                         genSkip(ifx,'z');
7202                                                 }
7203                                         }
7204                                                 pic16_emitpLabel(falselbl->key);
7205                                                 break;
7206
7207                         } // switch size
7208           
7209                         ifx->generated = 1;
7210                         goto release ;
7211             
7212
7213           } else if(AOP_TYPE(right) == AOP_CRY ) {
7214             /* we know the left is not a bit, but that the right is */
7215             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7216             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7217                       pic16_popGet(AOP(right),offset));
7218             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7219
7220             /* if the two are equal, then W will be 0 and the Z bit is set
7221              * we could test Z now, or go ahead and check the high order bytes if
7222              * the variable we're comparing is larger than a byte. */
7223
7224             while(--size)
7225               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7226
7227             if ( IC_TRUE(ifx) ) {
7228               emitSKPNZ;
7229               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7230               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7231             } else {
7232               emitSKPZ;
7233               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7234               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7235             }
7236
7237           } else {
7238             /* They're both variables that are larger than bits */
7239             int s = size;
7240
7241             tlbl = newiTempLabel(NULL);
7242
7243             while(size--) {
7244               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7245               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7246
7247               if ( IC_TRUE(ifx) ) {
7248                 if(size) {
7249                   emitSKPZ;
7250                 
7251                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7252
7253                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7254                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7255                 } else {
7256                   emitSKPNZ;
7257
7258                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7259
7260
7261                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7262                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7263                 }
7264               } else {
7265                 emitSKPZ;
7266
7267                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7268
7269                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7270                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7271               }
7272               offset++;
7273             }
7274             if(s>1 && IC_TRUE(ifx)) {
7275               pic16_emitpLabel(tlbl->key);
7276               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7277             }
7278           }
7279         }
7280         /* mark the icode as generated */
7281         ifx->generated = 1;
7282         goto release ;
7283     }
7284
7285     /* if they are both bit variables */
7286     if (AOP_TYPE(left) == AOP_CRY &&
7287         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7288         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7289         if(AOP_TYPE(right) == AOP_LIT){
7290             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7291             if(lit == 0L){
7292                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7293                 pic16_emitcode("cpl","c");
7294             } else if(lit == 1L) {
7295                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7296             } else {
7297                 pic16_emitcode("clr","c");
7298             }
7299             /* AOP_TYPE(right) == AOP_CRY */
7300         } else {
7301             symbol *lbl = newiTempLabel(NULL);
7302             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7303             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7304             pic16_emitcode("cpl","c");
7305             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7306         }
7307         /* c = 1 if egal */
7308         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7309             pic16_outBitC(result);
7310             goto release ;
7311         }
7312         if (ifx) {
7313             genIfxJump (ifx,"c");
7314             goto release ;
7315         }
7316         /* if the result is used in an arithmetic operation
7317         then put the result in place */
7318         pic16_outBitC(result);
7319     } else {
7320       
7321       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7322       gencjne(left,right,result,ifx);
7323 /*
7324       if(ifx) 
7325         gencjne(left,right,newiTempLabel(NULL));
7326       else {
7327         if(IC_TRUE(ifx)->key)
7328           gencjne(left,right,IC_TRUE(ifx)->key);
7329         else
7330           gencjne(left,right,IC_FALSE(ifx)->key);
7331         ifx->generated = 1;
7332         goto release ;
7333       }
7334       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7335         pic16_aopPut(AOP(result),"a",0);
7336         goto release ;
7337       }
7338
7339       if (ifx) {
7340         genIfxJump (ifx,"a");
7341         goto release ;
7342       }
7343 */
7344       /* if the result is used in an arithmetic operation
7345          then put the result in place */
7346 /*
7347       if (AOP_TYPE(result) != AOP_CRY) 
7348         pic16_outAcc(result);
7349 */
7350       /* leave the result in acc */
7351     }
7352
7353 release:
7354     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7355     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7356     pic16_freeAsmop(result,NULL,ic,TRUE);
7357 }
7358 #endif
7359
7360 /*-----------------------------------------------------------------*/
7361 /* ifxForOp - returns the icode containing the ifx for operand     */
7362 /*-----------------------------------------------------------------*/
7363 static iCode *ifxForOp ( operand *op, iCode *ic )
7364 {
7365   FENTRY2;
7366
7367     /* if true symbol then needs to be assigned */
7368     if (IS_TRUE_SYMOP(op))
7369         return NULL ;
7370
7371     /* if this has register type condition and
7372     the next instruction is ifx with the same operand
7373     and live to of the operand is upto the ifx only then */
7374     if (ic->next
7375         && ic->next->op == IFX
7376         && IC_COND(ic->next)->key == op->key
7377         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7378         ) {
7379                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7380           return ic->next;
7381     }
7382
7383     /*
7384     if (ic->next &&
7385         ic->next->op == IFX &&
7386         IC_COND(ic->next)->key == op->key) {
7387       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7388       return ic->next;
7389     }
7390     */
7391
7392     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7393     if (ic->next &&
7394         ic->next->op == IFX)
7395       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7396
7397     if (ic->next &&
7398         ic->next->op == IFX &&
7399         IC_COND(ic->next)->key == op->key) {
7400       DEBUGpic16_emitcode ("; "," key is okay");
7401       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7402                            OP_SYMBOL(op)->liveTo,
7403                            ic->next->seq);
7404     }
7405
7406 #if 0
7407     /* the code below is completely untested
7408      * it just allows ulong2fs.c compile -- VR */
7409          
7410     ic = ic->next;
7411     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7412                                         __FILE__, __FUNCTION__, __LINE__);
7413         
7414     /* if this has register type condition and
7415     the next instruction is ifx with the same operand
7416     and live to of the operand is upto the ifx only then */
7417     if (ic->next &&
7418         ic->next->op == IFX &&
7419         IC_COND(ic->next)->key == op->key &&
7420         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7421         return ic->next;
7422
7423     if (ic->next &&
7424         ic->next->op == IFX &&
7425         IC_COND(ic->next)->key == op->key) {
7426       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7427       return ic->next;
7428     }
7429
7430     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7431                                         __FILE__, __FUNCTION__, __LINE__);
7432
7433 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7434 #endif
7435
7436     return NULL;
7437 }
7438 /*-----------------------------------------------------------------*/
7439 /* genAndOp - for && operation                                     */
7440 /*-----------------------------------------------------------------*/
7441 static void genAndOp (iCode *ic)
7442 {
7443   operand *left,*right, *result;
7444 /*     symbol *tlbl; */
7445
7446     FENTRY;
7447
7448     /* note here that && operations that are in an
7449     if statement are taken away by backPatchLabels
7450     only those used in arthmetic operations remain */
7451     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7452     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7453     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7454
7455     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7456
7457     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7458     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7459     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7460
7461     /* if both are bit variables */
7462 /*     if (AOP_TYPE(left) == AOP_CRY && */
7463 /*         AOP_TYPE(right) == AOP_CRY ) { */
7464 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7465 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7466 /*         pic16_outBitC(result); */
7467 /*     } else { */
7468 /*         tlbl = newiTempLabel(NULL); */
7469 /*         pic16_toBoolean(left);     */
7470 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7471 /*         pic16_toBoolean(right); */
7472 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7473 /*         pic16_outBitAcc(result); */
7474 /*     } */
7475
7476     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7477     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7478     pic16_freeAsmop(result,NULL,ic,TRUE);
7479 }
7480
7481
7482 /*-----------------------------------------------------------------*/
7483 /* genOrOp - for || operation                                      */
7484 /*-----------------------------------------------------------------*/
7485 /*
7486   tsd pic port -
7487   modified this code, but it doesn't appear to ever get called
7488 */
7489
7490 static void genOrOp (iCode *ic)
7491 {
7492   operand *left,*right, *result;
7493   symbol *tlbl;
7494
7495     FENTRY;  
7496
7497   /* note here that || operations that are in an
7498     if statement are taken away by backPatchLabels
7499     only those used in arthmetic operations remain */
7500     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7501     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7502     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7503
7504     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7505
7506     /* if both are bit variables */
7507     if (AOP_TYPE(left) == AOP_CRY &&
7508         AOP_TYPE(right) == AOP_CRY ) {
7509       pic16_emitcode("clrc","");
7510       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7511                AOP(left)->aopu.aop_dir,
7512                AOP(left)->aopu.aop_dir);
7513       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7514                AOP(right)->aopu.aop_dir,
7515                AOP(right)->aopu.aop_dir);
7516       pic16_emitcode("setc","");
7517
7518     } else {
7519         tlbl = newiTempLabel(NULL);
7520         pic16_toBoolean(left);
7521         emitSKPZ;
7522         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7523         pic16_toBoolean(right);
7524         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7525
7526         pic16_outBitAcc(result);
7527     }
7528
7529     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7530     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7531     pic16_freeAsmop(result,NULL,ic,TRUE);            
7532 }
7533
7534 /*-----------------------------------------------------------------*/
7535 /* isLiteralBit - test if lit == 2^n                               */
7536 /*-----------------------------------------------------------------*/
7537 static int isLiteralBit(unsigned long lit)
7538 {
7539     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7540     0x100L,0x200L,0x400L,0x800L,
7541     0x1000L,0x2000L,0x4000L,0x8000L,
7542     0x10000L,0x20000L,0x40000L,0x80000L,
7543     0x100000L,0x200000L,0x400000L,0x800000L,
7544     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7545     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7546     int idx;
7547     
7548     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7549     for(idx = 0; idx < 32; idx++)
7550         if(lit == pw[idx])
7551             return idx+1;
7552     return 0;
7553 }
7554
7555 /*-----------------------------------------------------------------*/
7556 /* continueIfTrue -                                                */
7557 /*-----------------------------------------------------------------*/
7558 static void continueIfTrue (iCode *ic)
7559 {
7560   FENTRY;
7561   if(IC_TRUE(ic))
7562     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7563   ic->generated = 1;
7564 }
7565
7566 /*-----------------------------------------------------------------*/
7567 /* jmpIfTrue -                                                     */
7568 /*-----------------------------------------------------------------*/
7569 static void jumpIfTrue (iCode *ic)
7570 {
7571   FENTRY;
7572   if(!IC_TRUE(ic))
7573     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7574   ic->generated = 1;
7575 }
7576
7577 /*-----------------------------------------------------------------*/
7578 /* jmpTrueOrFalse -                                                */
7579 /*-----------------------------------------------------------------*/
7580 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7581 {
7582   // ugly but optimized by peephole
7583   FENTRY;
7584   if(IC_TRUE(ic)){
7585     symbol *nlbl = newiTempLabel(NULL);
7586       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7587       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7588       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7589       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7590   } else {
7591     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7592     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7593   }
7594   ic->generated = 1;
7595 }
7596
7597 /*-----------------------------------------------------------------*/
7598 /* genAnd  - code for and                                          */
7599 /*-----------------------------------------------------------------*/
7600 static void genAnd (iCode *ic, iCode *ifx)
7601 {
7602   operand *left, *right, *result;
7603   int size, offset=0;  
7604   unsigned long lit = 0L;
7605   int bytelit = 0;
7606   resolvedIfx rIfx;
7607
7608     FENTRY;
7609     
7610   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7611   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7612   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7613
7614   resolveIfx(&rIfx,ifx);
7615
7616   /* if left is a literal & right is not then exchange them */
7617   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7618       AOP_NEEDSACC(left)) {
7619     operand *tmp = right ;
7620     right = left;
7621     left = tmp;
7622   }
7623
7624   /* if result = right then exchange them */
7625   if(pic16_sameRegs(AOP(result),AOP(right))){
7626     operand *tmp = right ;
7627     right = left;
7628     left = tmp;
7629   }
7630
7631   /* if right is bit then exchange them */
7632   if (AOP_TYPE(right) == AOP_CRY &&
7633       AOP_TYPE(left) != AOP_CRY){
7634     operand *tmp = right ;
7635     right = left;
7636     left = tmp;
7637   }
7638   if(AOP_TYPE(right) == AOP_LIT)
7639     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7640
7641   size = AOP_SIZE(result);
7642
7643   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7644
7645   // if(bit & yy)
7646   // result = bit & yy;
7647   if (AOP_TYPE(left) == AOP_CRY){
7648     // c = bit & literal;
7649     if(AOP_TYPE(right) == AOP_LIT){
7650       if(lit & 1) {
7651         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7652           // no change
7653           goto release;
7654         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7655       } else {
7656         // bit(result) = 0;
7657         if(size && (AOP_TYPE(result) == AOP_CRY)){
7658           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7659           goto release;
7660         }
7661         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7662           jumpIfTrue(ifx);
7663           goto release;
7664         }
7665         pic16_emitcode("clr","c");
7666       }
7667     } else {
7668       if (AOP_TYPE(right) == AOP_CRY){
7669         // c = bit & bit;
7670         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7671         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7672       } else {
7673         // c = bit & val;
7674         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7675         // c = lsb
7676         pic16_emitcode("rrc","a");
7677         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7678       }
7679     }
7680     // bit = c
7681     // val = c
7682     if(size)
7683       pic16_outBitC(result);
7684     // if(bit & ...)
7685     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7686       genIfxJump(ifx, "c");           
7687     goto release ;
7688   }
7689
7690   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7691   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7692   if((AOP_TYPE(right) == AOP_LIT) &&
7693      (AOP_TYPE(result) == AOP_CRY) &&
7694      (AOP_TYPE(left) != AOP_CRY)){
7695     int posbit = isLiteralBit(lit);
7696     /* left &  2^n */
7697     if(posbit){
7698       posbit--;
7699       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7700       // bit = left & 2^n
7701       if(size)
7702         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7703       // if(left &  2^n)
7704       else{
7705         if(ifx){
7706 /*
7707           if(IC_TRUE(ifx)) {
7708             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7709             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7710           } else {
7711             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7712             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7713           }
7714 */
7715         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7716         size = AOP_SIZE(left);
7717
7718         {
7719           int bp = posbit, ofs=0;
7720           
7721             while(bp > 7) {
7722               bp -= 8;
7723               ofs++;
7724             }
7725
7726           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7727                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7728
7729         }
7730 /*
7731           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7732                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7733 */
7734           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7735           
7736           ifx->generated = 1;
7737         }
7738         goto release;
7739       }
7740     } else {
7741       symbol *tlbl = newiTempLabel(NULL);
7742       int sizel = AOP_SIZE(left);
7743
7744       if(size)
7745         emitSETC;
7746
7747       while(sizel--) {
7748         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7749
7750           /* patch provided by Aaron Colwell */
7751           if((posbit = isLiteralBit(bytelit)) != 0) {
7752               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7753                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7754                                                 (posbit-1),0, PO_GPR_REGISTER));
7755
7756               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7757 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7758           } else {
7759               if (bytelit == 0xff) {
7760                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7761                    * a peephole could optimize it out -- VR */
7762                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7763               } else {
7764                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7765                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7766               }
7767
7768               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7769                             pic16_popGetLabel(tlbl->key));
7770           }
7771         
7772 #if 0
7773           /* old code, left here for reference -- VR 09/2004 */
7774           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7775           // byte ==  2^n ?
7776           if((posbit = isLiteralBit(bytelit)) != 0)
7777             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7778           else{
7779             if(bytelit != 0x0FFL)
7780               pic16_emitcode("anl","a,%s",
7781                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7782             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7783           }
7784 #endif
7785         }
7786         offset++;
7787       }
7788       // bit = left & literal
7789       if(size) {
7790         emitCLRC;
7791         pic16_emitpLabel(tlbl->key);
7792       }
7793       // if(left & literal)
7794       else {
7795         if(ifx) {
7796           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7797           ifx->generated = 1;
7798         }
7799         pic16_emitpLabel(tlbl->key);
7800         goto release;
7801       }
7802     }
7803
7804     pic16_outBitC(result);
7805     goto release ;
7806   }
7807
7808   /* if left is same as result */
7809   if(pic16_sameRegs(AOP(result),AOP(left))){
7810     int know_W = -1;
7811     for(;size--; offset++,lit>>=8) {
7812       if(AOP_TYPE(right) == AOP_LIT){
7813         switch(lit & 0xff) {
7814         case 0x00:
7815           /*  and'ing with 0 has clears the result */
7816 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7817           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7818           break;
7819         case 0xff:
7820           /* and'ing with 0xff is a nop when the result and left are the same */
7821           break;
7822
7823         default:
7824           {
7825             int p = pic16_my_powof2( (~lit) & 0xff );
7826             if(p>=0) {
7827               /* only one bit is set in the literal, so use a bcf instruction */
7828 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7829               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7830
7831             } else {
7832               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7833               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7834               if(know_W != (lit&0xff))
7835                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7836               know_W = lit &0xff;
7837               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7838             }
7839           }    
7840         }
7841       } else {
7842         if (AOP_TYPE(left) == AOP_ACC) {
7843           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7844         } else {                    
7845           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7846           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7847
7848         }
7849       }
7850     }
7851
7852   } else {
7853     // left & result in different registers
7854     if(AOP_TYPE(result) == AOP_CRY){
7855       // result = bit
7856       // if(size), result in bit
7857       // if(!size && ifx), conditional oper: if(left & right)
7858       symbol *tlbl = newiTempLabel(NULL);
7859       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7860       if(size)
7861         pic16_emitcode("setb","c");
7862       while(sizer--){
7863         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7864         pic16_emitcode("anl","a,%s",
7865                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7866         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7867         offset++;
7868       }
7869       if(size){
7870         CLRC;
7871         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7872         pic16_outBitC(result);
7873       } else if(ifx)
7874         jmpTrueOrFalse(ifx, tlbl);
7875     } else {
7876       for(;(size--);offset++) {
7877         // normal case
7878         // result = left & right
7879         if(AOP_TYPE(right) == AOP_LIT){
7880           int t = (lit >> (offset*8)) & 0x0FFL;
7881           switch(t) { 
7882           case 0x00:
7883             pic16_emitcode("clrf","%s",
7884                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7885             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7886             break;
7887           case 0xff:
7888             pic16_emitcode("movf","%s,w",
7889                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7890             pic16_emitcode("movwf","%s",
7891                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7892             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7893             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7894             break;
7895           default:
7896             pic16_emitcode("movlw","0x%x",t);
7897             pic16_emitcode("andwf","%s,w",
7898                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7899             pic16_emitcode("movwf","%s",
7900                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7901               
7902             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7903             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7904             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7905           }
7906           continue;
7907         }
7908
7909         if (AOP_TYPE(left) == AOP_ACC) {
7910           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7911           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7912         } else {
7913           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7914           pic16_emitcode("andwf","%s,w",
7915                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7916           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7917           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7918         }
7919         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7920         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7921       }
7922     }
7923   }
7924
7925   release :
7926     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7927   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7928   pic16_freeAsmop(result,NULL,ic,TRUE);     
7929 }
7930
7931 /*-----------------------------------------------------------------*/
7932 /* genOr  - code for or                                            */
7933 /*-----------------------------------------------------------------*/
7934 static void genOr (iCode *ic, iCode *ifx)
7935 {
7936     operand *left, *right, *result;
7937     int size, offset=0;
7938     unsigned long lit = 0L;
7939
7940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7941     FENTRY;
7942
7943     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7944     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7945     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7946
7947     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7948
7949     /* if left is a literal & right is not then exchange them */
7950     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7951         AOP_NEEDSACC(left)) {
7952         operand *tmp = right ;
7953         right = left;
7954         left = tmp;
7955     }
7956
7957     /* if result = right then exchange them */
7958     if(pic16_sameRegs(AOP(result),AOP(right))){
7959         operand *tmp = right ;
7960         right = left;
7961         left = tmp;
7962     }
7963
7964     /* if right is bit then exchange them */
7965     if (AOP_TYPE(right) == AOP_CRY &&
7966         AOP_TYPE(left) != AOP_CRY){
7967         operand *tmp = right ;
7968         right = left;
7969         left = tmp;
7970     }
7971
7972     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7973
7974     if(AOP_TYPE(right) == AOP_LIT)
7975         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7976
7977     size = AOP_SIZE(result);
7978
7979     // if(bit | yy)
7980     // xx = bit | yy;
7981     if (AOP_TYPE(left) == AOP_CRY){
7982         if(AOP_TYPE(right) == AOP_LIT){
7983             // c = bit & literal;
7984             if(lit){
7985                 // lit != 0 => result = 1
7986                 if(AOP_TYPE(result) == AOP_CRY){
7987                   if(size)
7988                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7989                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7990                   //     AOP(result)->aopu.aop_dir,
7991                   //     AOP(result)->aopu.aop_dir);
7992                     else if(ifx)
7993                         continueIfTrue(ifx);
7994                     goto release;
7995                 }
7996             } else {
7997                 // lit == 0 => result = left
7998                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7999                     goto release;
8000                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8001             }
8002         } else {
8003             if (AOP_TYPE(right) == AOP_CRY){
8004               if(pic16_sameRegs(AOP(result),AOP(left))){
8005                 // c = bit | bit;
8006                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8007                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8008                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8009
8010                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8011                          AOP(result)->aopu.aop_dir,
8012                          AOP(result)->aopu.aop_dir);
8013                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8014                          AOP(right)->aopu.aop_dir,
8015                          AOP(right)->aopu.aop_dir);
8016                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8017                          AOP(result)->aopu.aop_dir,
8018                          AOP(result)->aopu.aop_dir);
8019               } else {
8020                 if( AOP_TYPE(result) == AOP_ACC) {
8021                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8022                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8023                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8024                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8025
8026                 } else {
8027
8028                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8029                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8030                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8031                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8032
8033                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8034                                  AOP(result)->aopu.aop_dir,
8035                                  AOP(result)->aopu.aop_dir);
8036                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8037                                  AOP(right)->aopu.aop_dir,
8038                                  AOP(right)->aopu.aop_dir);
8039                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8040                                  AOP(left)->aopu.aop_dir,
8041                                  AOP(left)->aopu.aop_dir);
8042                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8043                                  AOP(result)->aopu.aop_dir,
8044                                  AOP(result)->aopu.aop_dir);
8045                 }
8046               }
8047             } else {
8048                 // c = bit | val;
8049                 symbol *tlbl = newiTempLabel(NULL);
8050                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8051
8052
8053                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8054                 if( AOP_TYPE(right) == AOP_ACC) {
8055                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8056                   emitSKPNZ;
8057                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8058                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8059                 }
8060
8061
8062
8063                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8064                     pic16_emitcode(";XXX setb","c");
8065                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8066                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8067                 pic16_toBoolean(right);
8068                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8069                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8070                     jmpTrueOrFalse(ifx, tlbl);
8071                     goto release;
8072                 } else {
8073                     CLRC;
8074                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8075                 }
8076             }
8077         }
8078         // bit = c
8079         // val = c
8080         if(size)
8081             pic16_outBitC(result);
8082         // if(bit | ...)
8083         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8084             genIfxJump(ifx, "c");           
8085         goto release ;
8086     }
8087
8088     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8089     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8090     if((AOP_TYPE(right) == AOP_LIT) &&
8091        (AOP_TYPE(result) == AOP_CRY) &&
8092        (AOP_TYPE(left) != AOP_CRY)){
8093         if(lit){
8094           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8095             // result = 1
8096             if(size)
8097                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8098             else 
8099                 continueIfTrue(ifx);
8100             goto release;
8101         } else {
8102           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8103             // lit = 0, result = boolean(left)
8104             if(size)
8105                 pic16_emitcode(";XXX setb","c");
8106             pic16_toBoolean(right);
8107             if(size){
8108                 symbol *tlbl = newiTempLabel(NULL);
8109                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8110                 CLRC;
8111                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8112             } else {
8113                 genIfxJump (ifx,"a");
8114                 goto release;
8115             }
8116         }
8117         pic16_outBitC(result);
8118         goto release ;
8119     }
8120
8121     /* if left is same as result */
8122     if(pic16_sameRegs(AOP(result),AOP(left))){
8123       int know_W = -1;
8124       for(;size--; offset++,lit>>=8) {
8125         if(AOP_TYPE(right) == AOP_LIT){
8126           if((lit & 0xff) == 0)
8127             /*  or'ing with 0 has no effect */
8128             continue;
8129           else {
8130             int p = pic16_my_powof2(lit & 0xff);
8131             if(p>=0) {
8132               /* only one bit is set in the literal, so use a bsf instruction */
8133               pic16_emitpcode(POC_BSF,
8134                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8135             } else {
8136               if(know_W != (lit & 0xff))
8137                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8138               know_W = lit & 0xff;
8139               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8140             }
8141                     
8142           }
8143         } else {
8144           if (AOP_TYPE(left) == AOP_ACC) {
8145             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8146 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8147           } else {                  
8148             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8149             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8150
8151 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8152 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8153
8154           }
8155         }
8156       }
8157     } else {
8158         // left & result in different registers
8159         if(AOP_TYPE(result) == AOP_CRY){
8160             // result = bit
8161             // if(size), result in bit
8162             // if(!size && ifx), conditional oper: if(left | right)
8163             symbol *tlbl = newiTempLabel(NULL);
8164             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8165             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8166
8167
8168             if(size)
8169                 pic16_emitcode(";XXX setb","c");
8170             while(sizer--){
8171                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8172                 pic16_emitcode(";XXX orl","a,%s",
8173                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8174                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8175                 offset++;
8176             }
8177             if(size){
8178                 CLRC;
8179                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8180                 pic16_outBitC(result);
8181             } else if(ifx)
8182                 jmpTrueOrFalse(ifx, tlbl);
8183         } else for(;(size--);offset++){
8184           // normal case
8185           // result = left & right
8186           if(AOP_TYPE(right) == AOP_LIT){
8187             int t = (lit >> (offset*8)) & 0x0FFL;
8188             switch(t) { 
8189             case 0x00:
8190               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8191               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8192
8193 //            pic16_emitcode("movf","%s,w",
8194 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8195 //            pic16_emitcode("movwf","%s",
8196 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8197               break;
8198             default:
8199               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8200               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8201               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8202
8203 //            pic16_emitcode("movlw","0x%x",t);
8204 //            pic16_emitcode("iorwf","%s,w",
8205 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8206 //            pic16_emitcode("movwf","%s",
8207 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8208               
8209             }
8210             continue;
8211           }
8212
8213           // faster than result <- left, anl result,right
8214           // and better if result is SFR
8215           if (AOP_TYPE(left) == AOP_ACC) {
8216             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8217 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8218           } else {
8219             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8220             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8221
8222 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8223 //          pic16_emitcode("iorwf","%s,w",
8224 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8225           }
8226           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8227 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8228         }
8229     }
8230
8231 release :
8232     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8233     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8234     pic16_freeAsmop(result,NULL,ic,TRUE);     
8235 }
8236
8237 /*-----------------------------------------------------------------*/
8238 /* genXor - code for xclusive or                                   */
8239 /*-----------------------------------------------------------------*/
8240 static void genXor (iCode *ic, iCode *ifx)
8241 {
8242   operand *left, *right, *result;
8243   int size, offset=0;
8244   unsigned long lit = 0L;
8245
8246   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8247   FENTRY;
8248
8249   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8250   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8251   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8252
8253   /* if left is a literal & right is not ||
8254      if left needs acc & right does not */
8255   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8256       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8257     operand *tmp = right ;
8258     right = left;
8259     left = tmp;
8260   }
8261
8262   /* if result = right then exchange them */
8263   if(pic16_sameRegs(AOP(result),AOP(right))){
8264     operand *tmp = right ;
8265     right = left;
8266     left = tmp;
8267   }
8268
8269   /* if right is bit then exchange them */
8270   if (AOP_TYPE(right) == AOP_CRY &&
8271       AOP_TYPE(left) != AOP_CRY){
8272     operand *tmp = right ;
8273     right = left;
8274     left = tmp;
8275   }
8276   if(AOP_TYPE(right) == AOP_LIT)
8277     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8278
8279   size = AOP_SIZE(result);
8280
8281   // if(bit ^ yy)
8282   // xx = bit ^ yy;
8283   if (AOP_TYPE(left) == AOP_CRY){
8284     if(AOP_TYPE(right) == AOP_LIT){
8285       // c = bit & literal;
8286       if(lit>>1){
8287         // lit>>1  != 0 => result = 1
8288         if(AOP_TYPE(result) == AOP_CRY){
8289           if(size)
8290             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8291             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8292           else if(ifx)
8293             continueIfTrue(ifx);
8294           goto release;
8295         }
8296         pic16_emitcode("setb","c");
8297       } else{
8298         // lit == (0 or 1)
8299         if(lit == 0){
8300           // lit == 0, result = left
8301           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8302             goto release;
8303           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8304         } else{
8305           // lit == 1, result = not(left)
8306           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8307             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8308             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8309             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8310             goto release;
8311           } else {
8312             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8313             pic16_emitcode("cpl","c");
8314           }
8315         }
8316       }
8317
8318     } else {
8319       // right != literal
8320       symbol *tlbl = newiTempLabel(NULL);
8321       if (AOP_TYPE(right) == AOP_CRY){
8322         // c = bit ^ bit;
8323         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8324       }
8325       else{
8326         int sizer = AOP_SIZE(right);
8327         // c = bit ^ val
8328         // if val>>1 != 0, result = 1
8329         pic16_emitcode("setb","c");
8330         while(sizer){
8331           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8332           if(sizer == 1)
8333             // test the msb of the lsb
8334             pic16_emitcode("anl","a,#0xfe");
8335           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8336           sizer--;
8337         }
8338         // val = (0,1)
8339         pic16_emitcode("rrc","a");
8340       }
8341       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8342       pic16_emitcode("cpl","c");
8343       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8344     }
8345     // bit = c
8346     // val = c
8347     if(size)
8348       pic16_outBitC(result);
8349     // if(bit | ...)
8350     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8351       genIfxJump(ifx, "c");           
8352     goto release ;
8353   }
8354
8355   if(pic16_sameRegs(AOP(result),AOP(left))){
8356     /* if left is same as result */
8357     for(;size--; offset++) {
8358       if(AOP_TYPE(right) == AOP_LIT){
8359         int t  = (lit >> (offset*8)) & 0x0FFL;
8360         if(t == 0x00L)
8361           continue;
8362         else
8363           if (IS_AOP_PREG(left)) {
8364             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8365             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8366             pic16_aopPut(AOP(result),"a",offset);
8367           } else {
8368             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8369             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8370             pic16_emitcode("xrl","%s,%s",
8371                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8372                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8373           }
8374       } else {
8375         if (AOP_TYPE(left) == AOP_ACC)
8376           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8377         else {
8378           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8379           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8380 /*
8381           if (IS_AOP_PREG(left)) {
8382             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8383             pic16_aopPut(AOP(result),"a",offset);
8384           } else
8385             pic16_emitcode("xrl","%s,a",
8386                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8387 */
8388         }
8389       }
8390     }
8391   } else {
8392     // left & result in different registers
8393     if(AOP_TYPE(result) == AOP_CRY){
8394       // result = bit
8395       // if(size), result in bit
8396       // if(!size && ifx), conditional oper: if(left ^ right)
8397       symbol *tlbl = newiTempLabel(NULL);
8398       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8399       if(size)
8400         pic16_emitcode("setb","c");
8401       while(sizer--){
8402         if((AOP_TYPE(right) == AOP_LIT) &&
8403            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8404           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8405         } else {
8406           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8407           pic16_emitcode("xrl","a,%s",
8408                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8409         }
8410         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8411         offset++;
8412       }
8413       if(size){
8414         CLRC;
8415         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8416         pic16_outBitC(result);
8417       } else if(ifx)
8418         jmpTrueOrFalse(ifx, tlbl);
8419     } else for(;(size--);offset++){
8420       // normal case
8421       // result = left & right
8422       if(AOP_TYPE(right) == AOP_LIT){
8423         int t = (lit >> (offset*8)) & 0x0FFL;
8424         switch(t) { 
8425         case 0x00:
8426           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8427           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8428           pic16_emitcode("movf","%s,w",
8429                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8430           pic16_emitcode("movwf","%s",
8431                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8432           break;
8433         case 0xff:
8434           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8435           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8436           pic16_emitcode("comf","%s,w",
8437                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8438           pic16_emitcode("movwf","%s",
8439                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8440           break;
8441         default:
8442           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8443           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8444           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8445           pic16_emitcode("movlw","0x%x",t);
8446           pic16_emitcode("xorwf","%s,w",
8447                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8448           pic16_emitcode("movwf","%s",
8449                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8450
8451         }
8452         continue;
8453       }
8454
8455       // faster than result <- left, anl result,right
8456       // and better if result is SFR
8457       if (AOP_TYPE(left) == AOP_ACC) {
8458         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8459         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8460       } else {
8461         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8462         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8463         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8464         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8465       }
8466       if ( AOP_TYPE(result) != AOP_ACC){
8467         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8468         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8469       }
8470     }
8471   }
8472
8473   release :
8474     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8475   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8476   pic16_freeAsmop(result,NULL,ic,TRUE);     
8477 }
8478
8479 /*-----------------------------------------------------------------*/
8480 /* genInline - write the inline code out                           */
8481 /*-----------------------------------------------------------------*/
8482 static void genInline (iCode *ic)
8483 {
8484   char *buffer, *bp, *bp1;
8485     
8486         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8487
8488         _G.inLine += (!options.asmpeep);
8489
8490         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8491         strcpy(buffer,IC_INLINE(ic));
8492         
8493         while((bp1=strstr(bp, "\\n"))) {
8494           *bp1++ = '\n';
8495           *bp1++ = ' ';
8496           bp = bp1;
8497         }
8498         bp = bp1 = buffer;
8499
8500 #if 0
8501   /* This is an experimental code for #pragma inline
8502      and is temporarily disabled for 2.5.0 release */
8503         if(asmInlineMap)
8504         {
8505           symbol *sym;
8506           char *s;
8507           char *cbuf;
8508           int cblen;
8509
8510             cbuf = Safe_strdup(buffer);
8511             cblen = strlen(buffer)+1;
8512             memset(cbuf, 0, cblen);
8513
8514             bp = buffer;
8515             bp1 = cbuf;
8516             while(*bp) {
8517               if(*bp != '%')*bp1++ = *bp++;
8518               else {
8519                 int i;
8520
8521                   bp++;
8522                   i = *bp - '0';
8523                   if(i>elementsInSet(asmInlineMap))break;
8524                   
8525                   bp++;
8526                   s = indexSet(asmInlineMap, i);
8527                   DEBUGpc("searching symbol s = `%s'", s);
8528                   sym = findSym(SymbolTab, NULL, s);
8529
8530                   if(sym->reqv) {
8531                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8532                   } else {
8533                     strcat(bp1, sym->rname);
8534                   }
8535                   
8536                   while(*bp1)bp1++;
8537               }
8538               
8539               if(strlen(bp1) > cblen - 16) {
8540                 int i = strlen(cbuf);
8541                 cblen += 50;
8542                 cbuf = realloc(cbuf, cblen);
8543                 memset(cbuf+i, 0, 50);
8544                 bp1 = cbuf + i;
8545               }
8546             }
8547             
8548             free(buffer);
8549             buffer = Safe_strdup( cbuf );
8550             free(cbuf);
8551             
8552             bp = bp1 = buffer;
8553         }
8554 #endif  /* 0 */
8555
8556         /* emit each line as a code */
8557         while (*bp) {
8558                 if (*bp == '\n') {
8559                         *bp++ = '\0';
8560
8561                         if(*bp1)
8562                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8563                         bp1 = bp;
8564                 } else {
8565                         if (*bp == ':') {
8566                                 bp++;
8567                                 *bp = '\0';
8568                                 bp++;
8569
8570                                 /* print label, use this special format with NULL directive
8571                                  * to denote that the argument should not be indented with tab */
8572                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8573                                 bp1 = bp;
8574                         } if (*bp == ';') {
8575                                 /* advance to end of line (prevent splitting of comments at ':' */
8576                                 while (*bp && *bp != '\n') {
8577                                         bp++;
8578                                 } // while
8579                         } else
8580                                 bp++;
8581                 }
8582         }
8583
8584         if ((bp1 != bp) && *bp1)
8585                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8586
8587
8588     Safe_free(buffer);
8589
8590     _G.inLine -= (!options.asmpeep);
8591 }
8592
8593 /*-----------------------------------------------------------------*/
8594 /* genRRC - rotate right with carry                                */
8595 /*-----------------------------------------------------------------*/
8596 static void genRRC (iCode *ic)
8597 {
8598   operand *left , *result ;
8599   int size, offset = 0, same;
8600
8601   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8602
8603   /* rotate right with carry */
8604   left = IC_LEFT(ic);
8605   result=IC_RESULT(ic);
8606   pic16_aopOp (left,ic,FALSE);
8607   pic16_aopOp (result,ic,TRUE);
8608
8609   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8610
8611   same = pic16_sameRegs(AOP(result),AOP(left));
8612
8613   size = AOP_SIZE(result);    
8614
8615   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8616
8617   /* get the lsb and put it into the carry */
8618   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8619
8620   offset = 0 ;
8621
8622   while(size--) {
8623
8624     if(same) {
8625       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8626     } else {
8627       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8628       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8629     }
8630
8631     offset++;
8632   }
8633
8634   pic16_freeAsmop(left,NULL,ic,TRUE);
8635   pic16_freeAsmop(result,NULL,ic,TRUE);
8636 }
8637
8638 /*-----------------------------------------------------------------*/
8639 /* genRLC - generate code for rotate left with carry               */
8640 /*-----------------------------------------------------------------*/
8641 static void genRLC (iCode *ic)
8642 {    
8643   operand *left , *result ;
8644   int size, offset = 0;
8645   int same;
8646
8647   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8648   /* rotate right with carry */
8649   left = IC_LEFT(ic);
8650   result=IC_RESULT(ic);
8651   pic16_aopOp (left,ic,FALSE);
8652   pic16_aopOp (result,ic,TRUE);
8653
8654   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8655
8656   same = pic16_sameRegs(AOP(result),AOP(left));
8657
8658   /* move it to the result */
8659   size = AOP_SIZE(result);    
8660
8661   /* get the msb and put it into the carry */
8662   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8663
8664   offset = 0 ;
8665
8666   while(size--) {
8667
8668     if(same) {
8669       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8670     } else {
8671       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8672       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8673     }
8674
8675     offset++;
8676   }
8677
8678
8679   pic16_freeAsmop(left,NULL,ic,TRUE);
8680   pic16_freeAsmop(result,NULL,ic,TRUE);
8681 }
8682
8683
8684 /* gpasm can get the highest order bit with HIGH/UPPER
8685  * so the following probably is not needed -- VR */
8686  
8687 /*-----------------------------------------------------------------*/
8688 /* genGetHbit - generates code get highest order bit               */
8689 /*-----------------------------------------------------------------*/
8690 static void genGetHbit (iCode *ic)
8691 {
8692     operand *left, *result;
8693     left = IC_LEFT(ic);
8694     result=IC_RESULT(ic);
8695     pic16_aopOp (left,ic,FALSE);
8696     pic16_aopOp (result,ic,FALSE);
8697
8698     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8699     /* get the highest order byte into a */
8700     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8701     if(AOP_TYPE(result) == AOP_CRY){
8702         pic16_emitcode("rlc","a");
8703         pic16_outBitC(result);
8704     }
8705     else{
8706         pic16_emitcode("rl","a");
8707         pic16_emitcode("anl","a,#0x01");
8708         pic16_outAcc(result);
8709     }
8710
8711
8712     pic16_freeAsmop(left,NULL,ic,TRUE);
8713     pic16_freeAsmop(result,NULL,ic,TRUE);
8714 }
8715
8716 #if 0
8717 /*-----------------------------------------------------------------*/
8718 /* AccRol - rotate left accumulator by known count                 */
8719 /*-----------------------------------------------------------------*/
8720 static void AccRol (int shCount)
8721 {
8722     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8723     shCount &= 0x0007;              // shCount : 0..7
8724     switch(shCount){
8725         case 0 :
8726             break;
8727         case 1 :
8728             pic16_emitcode("rl","a");
8729             break;
8730         case 2 :
8731             pic16_emitcode("rl","a");
8732             pic16_emitcode("rl","a");
8733             break;
8734         case 3 :
8735             pic16_emitcode("swap","a");
8736             pic16_emitcode("rr","a");
8737             break;
8738         case 4 :
8739             pic16_emitcode("swap","a");
8740             break;
8741         case 5 :
8742             pic16_emitcode("swap","a");
8743             pic16_emitcode("rl","a");
8744             break;
8745         case 6 :
8746             pic16_emitcode("rr","a");
8747             pic16_emitcode("rr","a");
8748             break;
8749         case 7 :
8750             pic16_emitcode("rr","a");
8751             break;
8752     }
8753 }
8754 #endif
8755
8756 /*-----------------------------------------------------------------*/
8757 /* AccLsh - left shift accumulator by known count                  */
8758 /*-----------------------------------------------------------------*/
8759 static void AccLsh (int shCount, int doMask)
8760 {
8761         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8762         switch(shCount){
8763                 case 0 :
8764                         return;
8765                         break;
8766                 case 1 :
8767                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8768                         break;
8769                 case 2 :
8770                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8771                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8772                         break;
8773                 case 3 :
8774                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8775                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8776                         break;
8777                 case 4 :
8778                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8779                         break;
8780                 case 5 :
8781                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8782                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8783                         break;
8784                 case 6 :
8785                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8786                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8787                         break;
8788                 case 7 :
8789                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8790                         break;
8791         }
8792         if (doMask) {
8793                 /* no masking is required in genPackBits */
8794                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8795         }
8796 }
8797
8798 /*-----------------------------------------------------------------*/
8799 /* AccRsh - right shift accumulator by known count                 */
8800 /*-----------------------------------------------------------------*/
8801 static void AccRsh (int shCount, int andmask)
8802 {
8803         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8804         switch(shCount){
8805                 case 0 :
8806                         return; break;
8807                 case 1 :
8808                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8809                         break;
8810                 case 2 :
8811                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8812                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8813                         break;
8814                 case 3 :
8815                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8816                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8817                         break;
8818                 case 4 :
8819                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8820                         break;
8821                 case 5 :
8822                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8823                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8824                         break;
8825                 case 6 :
8826                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8827                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8828                         break;
8829                 case 7 :
8830                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8831                         break;
8832         }
8833         
8834         if(andmask)
8835                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8836         else
8837                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8838 }
8839
8840 #if 0
8841 /*-----------------------------------------------------------------*/
8842 /* AccSRsh - signed right shift accumulator by known count                 */
8843 /*-----------------------------------------------------------------*/
8844 static void AccSRsh (int shCount)
8845 {
8846     symbol *tlbl ;
8847     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8848     if(shCount != 0){
8849         if(shCount == 1){
8850             pic16_emitcode("mov","c,acc.7");
8851             pic16_emitcode("rrc","a");
8852         } else if(shCount == 2){
8853             pic16_emitcode("mov","c,acc.7");
8854             pic16_emitcode("rrc","a");
8855             pic16_emitcode("mov","c,acc.7");
8856             pic16_emitcode("rrc","a");
8857         } else {
8858             tlbl = newiTempLabel(NULL);
8859             /* rotate right accumulator */
8860             AccRol(8 - shCount);
8861             /* and kill the higher order bits */
8862             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8863             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8864             pic16_emitcode("orl","a,#0x%02x",
8865                      (unsigned char)~SRMask[shCount]);
8866             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8867         }
8868     }
8869 }
8870 #endif
8871
8872 /*-----------------------------------------------------------------*/
8873 /* shiftR1Left2Result - shift right one byte from left to result   */
8874 /*-----------------------------------------------------------------*/
8875 static void shiftR1Left2ResultSigned (operand *left, int offl,
8876                                 operand *result, int offr,
8877                                 int shCount)
8878 {
8879   int same;
8880
8881   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8882
8883   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8884
8885   switch(shCount) {
8886   case 1:
8887     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8888     if(same) 
8889       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8890     else {
8891       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8892       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8893     }
8894
8895     break;
8896   case 2:
8897
8898     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8899     if(same) 
8900       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8901     else {
8902       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8903       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8904     }
8905     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8906     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8907
8908     break;
8909
8910   case 3:
8911     if(same)
8912       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8913     else {
8914       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8915       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8916     }
8917
8918     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8919     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8920     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8921
8922     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8923     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8924
8925     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8926     break;
8927
8928   case 4:
8929     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8930     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8931     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8932     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8933     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8934     break;
8935   case 5:
8936     if(same) {
8937       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8938     } else {
8939       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8940       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8941     }
8942     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8943     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8944     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8945     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8946     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8947     break;
8948
8949   case 6:
8950     if(same) {
8951       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8952       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8953       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8954       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8955       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8956       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8957     } else {
8958       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8959       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8960       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8961       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8962       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8963     }
8964     break;
8965
8966   case 7:
8967     if(same) {
8968       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8969       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8970       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8971       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8972     } else {
8973       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8974       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8975       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8976     }
8977
8978   default:
8979     break;
8980   }
8981 }
8982
8983 /*-----------------------------------------------------------------*/
8984 /* shiftR1Left2Result - shift right one byte from left to result   */
8985 /*-----------------------------------------------------------------*/
8986 static void shiftR1Left2Result (operand *left, int offl,
8987                                 operand *result, int offr,
8988                                 int shCount, int sign)
8989 {
8990   int same;
8991
8992   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8993
8994   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8995
8996   /* Copy the msb into the carry if signed. */
8997   if(sign) {
8998     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8999     return;
9000   }
9001
9002
9003
9004   switch(shCount) {
9005   case 1:
9006     emitCLRC;
9007     if(same) 
9008       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9009     else {
9010       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9012     }
9013     break;
9014   case 2:
9015     emitCLRC;
9016     if(same) {
9017       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9018     } else {
9019       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9020       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9021     }
9022     emitCLRC;
9023     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9024
9025     break;
9026   case 3:
9027     if(same)
9028       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9029     else {
9030       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9031       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9032     }
9033
9034     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9035     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9036     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9037     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9038     break;
9039       
9040   case 4:
9041     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9042     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9043     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9044     break;
9045
9046   case 5:
9047     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9048     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9049     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9050     //emitCLRC;
9051     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9052
9053     break;
9054   case 6:
9055
9056     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9057     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9058     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9059     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9060     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9061     break;
9062
9063   case 7:
9064
9065     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9066     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9067     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9068
9069     break;
9070
9071   default:
9072     break;
9073   }
9074 }
9075
9076 /*-----------------------------------------------------------------*/
9077 /* shiftL1Left2Result - shift left one byte from left to result    */
9078 /*-----------------------------------------------------------------*/
9079 static void shiftL1Left2Result (operand *left, int offl,
9080                                 operand *result, int offr, int shCount)
9081 {
9082   int same;
9083
9084   //    char *l;
9085   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9086
9087   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9088   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9089     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9090     //    MOVA(l);
9091     /* shift left accumulator */
9092     //AccLsh(shCount, 1); // don't comment out just yet...
9093   //    pic16_aopPut(AOP(result),"a",offr);
9094
9095   switch(shCount) {
9096   case 1:
9097     /* Shift left 1 bit position */
9098     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9099     if(same) {
9100       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9101     } else {
9102       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9103       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9104     }
9105     break;
9106   case 2:
9107     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9108     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9109     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9110     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9111     break;
9112   case 3:
9113     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9114     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9115     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9116     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9117     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9118     break;
9119   case 4:
9120     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9121     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9122     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9123     break;
9124   case 5:
9125     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9126     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9127     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9128     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9129     break;
9130   case 6:
9131     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9132     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9133     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9134     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9135     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9136     break;
9137   case 7:
9138     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9139     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9140     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9141     break;
9142
9143   default:
9144     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9145   }
9146
9147 }
9148
9149 /*-----------------------------------------------------------------*/
9150 /* movLeft2Result - move byte from left to result                  */
9151 /*-----------------------------------------------------------------*/
9152 static void movLeft2Result (operand *left, int offl,
9153                             operand *result, int offr)
9154 {
9155   char *l;
9156   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9157   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9158     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9159
9160     if (*l == '@' && (IS_AOP_PREG(result))) {
9161       pic16_emitcode("mov","a,%s",l);
9162       pic16_aopPut(AOP(result),"a",offr);
9163     } else {
9164       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9165       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9166     }
9167   }
9168 }
9169
9170 /*-----------------------------------------------------------------*/
9171 /* shiftL2Left2Result - shift left two bytes from left to result   */
9172 /*-----------------------------------------------------------------*/
9173 static void shiftL2Left2Result (operand *left, int offl,
9174                                 operand *result, int offr, int shCount)
9175 {
9176   int same = pic16_sameRegs(AOP(result), AOP(left));
9177   int i;
9178
9179   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9180
9181   if (same && (offl != offr)) { // shift bytes
9182     if (offr > offl) {
9183        for(i=1;i>-1;i--) {
9184          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9185          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9186        }
9187     } else { // just treat as different later on
9188                 same = 0;
9189     }
9190   }
9191
9192   if(same) {
9193     switch(shCount) {
9194     case 0:
9195       break;
9196     case 1:
9197     case 2:
9198     case 3:
9199
9200       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9201       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9202       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9203
9204       while(--shCount) {
9205                 emitCLRC;
9206                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9207                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9208       }
9209
9210       break;
9211     case 4:
9212     case 5:
9213       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9214       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9215       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9216       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9217       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9218       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9219       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9220       if(shCount >=5) {
9221                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9222                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9223       }
9224       break;
9225     case 6:
9226       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9227       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9228       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9229       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9230       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9231       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9232       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9233       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9234       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9235       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9236       break;
9237     case 7:
9238       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9239       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9240       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9241       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9242       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9243     }
9244
9245   } else {
9246     switch(shCount) {
9247     case 0:
9248       break;
9249     case 1:
9250     case 2:
9251     case 3:
9252       /* note, use a mov/add for the shift since the mov has a
9253          chance of getting optimized out */
9254       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9255       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9256       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9257       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9258       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9259
9260       while(--shCount) {
9261                 emitCLRC;
9262                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9263                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9264       }
9265       break;
9266
9267     case 4:
9268     case 5:
9269       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9270       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9271       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9272       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9273       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9274       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9275       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9276       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9277
9278
9279       if(shCount == 5) {
9280                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9281                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9282       }
9283       break;
9284     case 6:
9285       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9286       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9287       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9288       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9289
9290       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9291       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9292       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9293       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9294       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9295       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9296       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9297       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9298       break;
9299     case 7:
9300       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9301       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9302       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9303       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9304       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9305     }
9306   }
9307
9308 }
9309 /*-----------------------------------------------------------------*/
9310 /* shiftR2Left2Result - shift right two bytes from left to result  */
9311 /*-----------------------------------------------------------------*/
9312 static void shiftR2Left2Result (operand *left, int offl,
9313                                 operand *result, int offr,
9314                                 int shCount, int sign)
9315 {
9316   int same = pic16_sameRegs(AOP(result), AOP(left));
9317   int i;
9318   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9319
9320   if (same && (offl != offr)) { // shift right bytes
9321     if (offr < offl) {
9322        for(i=0;i<2;i++) {
9323          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9324          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9325        }
9326     } else { // just treat as different later on
9327                 same = 0;
9328     }
9329   }
9330
9331   switch(shCount) {
9332   case 0:
9333     break;
9334   case 1:
9335   case 2:
9336   case 3:
9337     /* obtain sign from left operand */
9338     if(sign)
9339       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9340     else
9341       emitCLRC;
9342
9343     if(same) {
9344       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9345       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9346     } else {
9347       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9348       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9349       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9350       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9351     }
9352
9353     while(--shCount) {
9354       if(sign)
9355         /* now get sign from already assigned result (avoid BANKSEL) */
9356         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9357       else
9358         emitCLRC;
9359       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9360       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9361     }
9362     break;
9363   case 4:
9364   case 5:
9365     if(same) {
9366
9367       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9368       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9369       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9370
9371       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9372       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9373       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9374       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9375     } else {
9376       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9377       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9378       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9379
9380       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9381       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9382       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9383       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9384       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9385     }
9386
9387     if(shCount >=5) {
9388       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9389       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9390     }
9391
9392     if(sign) {
9393       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9394       pic16_emitpcode(POC_BTFSC, 
9395                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9396       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9397     }
9398
9399     break;
9400
9401   case 6:
9402     if(same) {
9403
9404       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9405       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9406
9407       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9408       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9409       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9410       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9411       if(sign) {
9412         pic16_emitpcode(POC_BTFSC, 
9413                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9414         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9415       }
9416       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9417       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9418       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9419       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9420     } else {
9421       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9422       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9423       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9424       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9425       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9426       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9427       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9428       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9429       if(sign) {
9430         pic16_emitpcode(POC_BTFSC, 
9431                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9432         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9433       }
9434       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9435       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9436
9437         
9438     }
9439
9440     break;
9441   case 7:
9442     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9443     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9444     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9445     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9446     if(sign) {
9447       emitSKPNC;
9448       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9449     } else 
9450       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9451   }
9452 }
9453
9454
9455 /*-----------------------------------------------------------------*/
9456 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9457 /*-----------------------------------------------------------------*/
9458 static void shiftLLeftOrResult (operand *left, int offl,
9459                                 operand *result, int offr, int shCount)
9460 {
9461     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9462
9463     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9464     /* shift left accumulator */
9465     AccLsh(shCount, 1);
9466     /* or with result */
9467     /* back to result */
9468     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9469 }
9470
9471 /*-----------------------------------------------------------------*/
9472 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9473 /*-----------------------------------------------------------------*/
9474 static void shiftRLeftOrResult (operand *left, int offl,
9475                                 operand *result, int offr, int shCount)
9476 {
9477     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9478     
9479     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9480     /* shift right accumulator */
9481     AccRsh(shCount, 1);
9482     /* or with result */
9483     /* back to result */
9484     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9485 }
9486
9487 /*-----------------------------------------------------------------*/
9488 /* genlshOne - left shift a one byte quantity by known count       */
9489 /*-----------------------------------------------------------------*/
9490 static void genlshOne (operand *result, operand *left, int shCount)
9491 {       
9492     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9493     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9494 }
9495
9496 /*-----------------------------------------------------------------*/
9497 /* genlshTwo - left shift two bytes by known amount != 0           */
9498 /*-----------------------------------------------------------------*/
9499 static void genlshTwo (operand *result,operand *left, int shCount)
9500 {
9501     int size;
9502     
9503     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9504     size = pic16_getDataSize(result);
9505
9506     /* if shCount >= 8 */
9507     if (shCount >= 8) {
9508         shCount -= 8 ;
9509
9510         if (size > 1){
9511             if (shCount)
9512                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9513             else 
9514                 movLeft2Result(left, LSB, result, MSB16);
9515         }
9516         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9517     }
9518
9519     /*  1 <= shCount <= 7 */
9520     else {  
9521         if(size == 1)
9522             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9523         else 
9524             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9525     }
9526 }
9527
9528 /*-----------------------------------------------------------------*/
9529 /* shiftLLong - shift left one long from left to result            */
9530 /* offr = LSB or MSB16                                             */
9531 /*-----------------------------------------------------------------*/
9532 static void shiftLLong (operand *left, operand *result, int offr )
9533 {
9534     int size = AOP_SIZE(result);
9535     int same = pic16_sameRegs(AOP(left),AOP(result));
9536         int i;
9537
9538     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9539
9540         if (same && (offr == MSB16)) { //shift one byte
9541                 for(i=size-1;i>=MSB16;i--) {
9542                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9543                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9544                 }
9545         } else {
9546                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9547         }
9548         
9549     if (size > LSB+offr ){
9550                 if (same) {
9551                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9552                 } else {
9553                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9554                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9555                 }
9556          }
9557
9558     if(size > MSB16+offr){
9559                 if (same) {
9560                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9561                 } else {
9562                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9563                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9564                 }
9565     }
9566
9567     if(size > MSB24+offr){
9568                 if (same) {
9569                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9570                 } else {
9571                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9572                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9573                 }
9574     }
9575
9576     if(size > MSB32+offr){
9577                 if (same) {
9578                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9579                 } else {
9580                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9581                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9582                 }
9583     }
9584     if(offr != LSB)
9585                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9586
9587 }
9588
9589 /*-----------------------------------------------------------------*/
9590 /* genlshFour - shift four byte by a known amount != 0             */
9591 /*-----------------------------------------------------------------*/
9592 static void genlshFour (operand *result, operand *left, int shCount)
9593 {
9594     int size;
9595
9596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9597     size = AOP_SIZE(result);
9598
9599     /* if shifting more that 3 bytes */
9600     if (shCount >= 24 ) {
9601         shCount -= 24;
9602         if (shCount)
9603             /* lowest order of left goes to the highest
9604             order of the destination */
9605             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9606         else
9607             movLeft2Result(left, LSB, result, MSB32);
9608
9609                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9610                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9611                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9612
9613         return;
9614     }
9615
9616     /* more than two bytes */
9617     else if ( shCount >= 16 ) {
9618         /* lower order two bytes goes to higher order two bytes */
9619         shCount -= 16;
9620         /* if some more remaining */
9621         if (shCount)
9622             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9623         else {
9624             movLeft2Result(left, MSB16, result, MSB32);
9625             movLeft2Result(left, LSB, result, MSB24);
9626         }
9627                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9628                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9629         return;
9630     }    
9631
9632     /* if more than 1 byte */
9633     else if ( shCount >= 8 ) {
9634         /* lower order three bytes goes to higher order  three bytes */
9635         shCount -= 8;
9636         if(size == 2){
9637             if(shCount)
9638                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9639             else
9640                 movLeft2Result(left, LSB, result, MSB16);
9641         }
9642         else{   /* size = 4 */
9643             if(shCount == 0){
9644                 movLeft2Result(left, MSB24, result, MSB32);
9645                 movLeft2Result(left, MSB16, result, MSB24);
9646                 movLeft2Result(left, LSB, result, MSB16);
9647                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9648             }
9649             else if(shCount == 1)
9650                 shiftLLong(left, result, MSB16);
9651             else{
9652                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9653                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9654                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9655                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9656             }
9657         }
9658     }
9659
9660     /* 1 <= shCount <= 7 */
9661     else if(shCount <= 3)
9662     { 
9663         shiftLLong(left, result, LSB);
9664         while(--shCount >= 1)
9665             shiftLLong(result, result, LSB);
9666     }
9667     /* 3 <= shCount <= 7, optimize */
9668     else{
9669         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9670         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9671         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9672     }
9673 }
9674
9675 /*-----------------------------------------------------------------*/
9676 /* genLeftShiftLiteral - left shifting by known count              */
9677 /*-----------------------------------------------------------------*/
9678 void pic16_genLeftShiftLiteral (operand *left,
9679                                  operand *right,
9680                                  operand *result,
9681                                  iCode *ic)
9682 {    
9683     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9684     int size;
9685
9686     FENTRY;
9687     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9688     pic16_freeAsmop(right,NULL,ic,TRUE);
9689
9690     pic16_aopOp(left,ic,FALSE);
9691     pic16_aopOp(result,ic,TRUE);
9692
9693     size = getSize(operandType(result));
9694
9695 #if VIEW_SIZE
9696     pic16_emitcode("; shift left ","result %d, left %d",size,
9697              AOP_SIZE(left));
9698 #endif
9699
9700     /* I suppose that the left size >= result size */
9701     if(shCount == 0){
9702         while(size--){
9703             movLeft2Result(left, size, result, size);
9704         }
9705     }
9706
9707     else if(shCount >= (size * 8))
9708         while(size--)
9709             pic16_aopPut(AOP(result),zero,size);
9710     else{
9711         switch (size) {
9712             case 1:
9713                 genlshOne (result,left,shCount);
9714                 break;
9715
9716             case 2:
9717             case 3:
9718                 genlshTwo (result,left,shCount);
9719                 break;
9720
9721             case 4:
9722                 genlshFour (result,left,shCount);
9723                 break;
9724         }
9725     }
9726     pic16_freeAsmop(left,NULL,ic,TRUE);
9727     pic16_freeAsmop(result,NULL,ic,TRUE);
9728 }
9729
9730 /*-----------------------------------------------------------------*
9731  * genMultiAsm - repeat assembly instruction for size of register.
9732  * if endian == 1, then the high byte (i.e base address + size of 
9733  * register) is used first else the low byte is used first;
9734  *-----------------------------------------------------------------*/
9735 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9736 {
9737
9738   int offset = 0;
9739
9740   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9741
9742   if(!reg)
9743     return;
9744
9745   if(!endian) {
9746     endian = 1;
9747   } else {
9748     endian = -1;
9749     offset = size-1;
9750   }
9751
9752   while(size--) {
9753     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9754     offset += endian;
9755   }
9756
9757 }
9758
9759 #if !(USE_GENERIC_SIGNED_SHIFT)
9760 /*-----------------------------------------------------------------*/
9761 /* genLeftShift - generates code for left shifting                 */
9762 /*-----------------------------------------------------------------*/
9763 static void genLeftShift (iCode *ic)
9764 {
9765   operand *left,*right, *result;
9766   int size, offset;
9767 //  char *l;
9768   symbol *tlbl , *tlbl1;
9769   pCodeOp *pctemp;
9770
9771   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9772
9773   right = IC_RIGHT(ic);
9774   left  = IC_LEFT(ic);
9775   result = IC_RESULT(ic);
9776
9777   pic16_aopOp(right,ic,FALSE);
9778
9779   /* if the shift count is known then do it 
9780      as efficiently as possible */
9781   if (AOP_TYPE(right) == AOP_LIT) {
9782     pic16_genLeftShiftLiteral (left,right,result,ic);
9783     return ;
9784   }
9785
9786   /* shift count is unknown then we have to form
9787    * a loop. Get the loop count in WREG : Note: we take
9788    * only the lower order byte since shifting
9789    * more than 32 bits make no sense anyway, ( the
9790    * largest size of an object can be only 32 bits ) */
9791   
9792   pic16_aopOp(left,ic,FALSE);
9793   pic16_aopOp(result,ic,FALSE);
9794
9795   /* now move the left to the result if they are not the
9796    * same, and if size > 1,
9797    * and if right is not same to result (!!!) -- VR */
9798   if (!pic16_sameRegs(AOP(left),AOP(result))
9799       && (AOP_SIZE(result) > 1)) {
9800
9801     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9802
9803     size = AOP_SIZE(result);
9804     offset=0;
9805     while (size--) {
9806
9807 #if 0
9808       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9809       if (*l == '@' && (IS_AOP_PREG(result))) {
9810
9811           pic16_emitcode("mov","a,%s",l);
9812           pic16_aopPut(AOP(result),"a",offset);
9813       } else
9814 #endif
9815       {
9816         /* we don't know if left is a literal or a register, take care -- VR */
9817         pic16_mov2f(AOP(result), AOP(left), offset);
9818       }
9819       offset++;
9820     }
9821   }
9822
9823   size = AOP_SIZE(result);
9824
9825   /* if it is only one byte then */
9826   if (size == 1) {
9827     if(optimized_for_speed) {
9828       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9829       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9830       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9831       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9832       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9833       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9834       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9835       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9836       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9837       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9838       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9839       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9840     } else {
9841
9842       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9843
9844       tlbl = newiTempLabel(NULL);
9845
9846 #if 1
9847       /* this is already done, why change it? */
9848       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9849                 pic16_mov2f(AOP(result), AOP(left), 0);
9850       }
9851 #endif
9852
9853       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9854       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9855       pic16_emitpLabel(tlbl->key);
9856       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9857       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9858       emitSKPC;
9859       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9860     }
9861     goto release ;
9862   }
9863     
9864   if (pic16_sameRegs(AOP(left),AOP(result))) {
9865
9866     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9867     
9868     tlbl = newiTempLabel(NULL);
9869     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9870     genMultiAsm(POC_RRCF, result, size,1);
9871     pic16_emitpLabel(tlbl->key);
9872     genMultiAsm(POC_RLCF, result, size,0);
9873     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9874     emitSKPC;
9875     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9876     goto release;
9877   }
9878
9879   //tlbl = newiTempLabel(NULL);
9880   //offset = 0 ;   
9881   //tlbl1 = newiTempLabel(NULL);
9882
9883   //reAdjustPreg(AOP(result));    
9884     
9885   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9886   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9887   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9888   //MOVA(l);
9889   //pic16_emitcode("add","a,acc");         
9890   //pic16_aopPut(AOP(result),"a",offset++);
9891   //while (--size) {
9892   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9893   //  MOVA(l);
9894   //  pic16_emitcode("rlc","a");         
9895   //  pic16_aopPut(AOP(result),"a",offset++);
9896   //}
9897   //reAdjustPreg(AOP(result));
9898
9899   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9900   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9901
9902
9903   tlbl = newiTempLabel(NULL);
9904   tlbl1= newiTempLabel(NULL);
9905
9906   size = AOP_SIZE(result);
9907   offset = 1;
9908
9909   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9910
9911   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9912
9913   /* offset should be 0, 1 or 3 */
9914   
9915   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9916   emitSKPNZ;
9917   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9918
9919   pic16_emitpcode(POC_MOVWF, pctemp);
9920
9921
9922   pic16_emitpLabel(tlbl->key);
9923
9924   emitCLRC;
9925   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9926   while(--size)
9927     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9928
9929   pic16_emitpcode(POC_DECFSZ,  pctemp);
9930   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9931   pic16_emitpLabel(tlbl1->key);
9932
9933   pic16_popReleaseTempReg(pctemp,1);
9934
9935
9936  release:
9937   pic16_freeAsmop (right,NULL,ic,TRUE);
9938   pic16_freeAsmop(left,NULL,ic,TRUE);
9939   pic16_freeAsmop(result,NULL,ic,TRUE);
9940 }
9941 #endif
9942
9943
9944 #if 0
9945 #error old code (left here for reference)
9946 /*-----------------------------------------------------------------*/
9947 /* genLeftShift - generates code for left shifting                 */
9948 /*-----------------------------------------------------------------*/
9949 static void genLeftShift (iCode *ic)
9950 {
9951   operand *left,*right, *result;
9952   int size, offset;
9953   char *l;
9954   symbol *tlbl , *tlbl1;
9955   pCodeOp *pctemp;
9956
9957   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9958
9959   right = IC_RIGHT(ic);
9960   left  = IC_LEFT(ic);
9961   result = IC_RESULT(ic);
9962
9963   pic16_aopOp(right,ic,FALSE);
9964
9965   /* if the shift count is known then do it 
9966      as efficiently as possible */
9967   if (AOP_TYPE(right) == AOP_LIT) {
9968     pic16_genLeftShiftLiteral (left,right,result,ic);
9969     return ;
9970   }
9971
9972   /* shift count is unknown then we have to form 
9973      a loop get the loop count in B : Note: we take
9974      only the lower order byte since shifting
9975      more that 32 bits make no sense anyway, ( the
9976      largest size of an object can be only 32 bits ) */  
9977
9978     
9979   pic16_aopOp(left,ic,FALSE);
9980   pic16_aopOp(result,ic,FALSE);
9981
9982   /* now move the left to the result if they are not the
9983      same */
9984   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9985       AOP_SIZE(result) > 1) {
9986
9987     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9988
9989     size = AOP_SIZE(result);
9990     offset=0;
9991     while (size--) {
9992       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9993       if (*l == '@' && (IS_AOP_PREG(result))) {
9994
9995         pic16_emitcode("mov","a,%s",l);
9996         pic16_aopPut(AOP(result),"a",offset);
9997       } else {
9998
9999         /* we don't know if left is a literal or a register, take care -- VR */
10000         pic16_mov2f(AOP(result), AOP(left), offset);
10001       }
10002       offset++;
10003     }
10004   }
10005
10006   size = AOP_SIZE(result);
10007
10008   /* if it is only one byte then */
10009   if (size == 1) {
10010     if(optimized_for_speed) {
10011       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10012       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10013       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10014       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10015       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10016       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10017       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10018       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10019       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10020       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10021       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10022       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10023     } else {
10024
10025       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10026
10027       tlbl = newiTempLabel(NULL);
10028       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10029                 pic16_mov2f(AOP(result), AOP(left), 0);
10030                 
10031 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10032 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10033       }
10034
10035       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10036       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10037       pic16_emitpLabel(tlbl->key);
10038       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10039       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10040       emitSKPC;
10041       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10042     }
10043     goto release ;
10044   }
10045     
10046   if (pic16_sameRegs(AOP(left),AOP(result))) {
10047
10048     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10049     
10050     tlbl = newiTempLabel(NULL);
10051     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10052     genMultiAsm(POC_RRCF, result, size,1);
10053     pic16_emitpLabel(tlbl->key);
10054     genMultiAsm(POC_RLCF, result, size,0);
10055     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10056     emitSKPC;
10057     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10058     goto release;
10059   }
10060
10061   //tlbl = newiTempLabel(NULL);
10062   //offset = 0 ;   
10063   //tlbl1 = newiTempLabel(NULL);
10064
10065   //reAdjustPreg(AOP(result));    
10066     
10067   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10068   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10069   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10070   //MOVA(l);
10071   //pic16_emitcode("add","a,acc");         
10072   //pic16_aopPut(AOP(result),"a",offset++);
10073   //while (--size) {
10074   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10075   //  MOVA(l);
10076   //  pic16_emitcode("rlc","a");         
10077   //  pic16_aopPut(AOP(result),"a",offset++);
10078   //}
10079   //reAdjustPreg(AOP(result));
10080
10081   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10082   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10083
10084
10085   tlbl = newiTempLabel(NULL);
10086   tlbl1= newiTempLabel(NULL);
10087
10088   size = AOP_SIZE(result);
10089   offset = 1;
10090
10091   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10092
10093   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10094
10095   /* offset should be 0, 1 or 3 */
10096   
10097   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10098   emitSKPNZ;
10099   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10100
10101   pic16_emitpcode(POC_MOVWF, pctemp);
10102
10103
10104   pic16_emitpLabel(tlbl->key);
10105
10106   emitCLRC;
10107   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10108   while(--size)
10109     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10110
10111   pic16_emitpcode(POC_DECFSZ,  pctemp);
10112   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10113   pic16_emitpLabel(tlbl1->key);
10114
10115   pic16_popReleaseTempReg(pctemp,1);
10116
10117
10118  release:
10119   pic16_freeAsmop (right,NULL,ic,TRUE);
10120   pic16_freeAsmop(left,NULL,ic,TRUE);
10121   pic16_freeAsmop(result,NULL,ic,TRUE);
10122 }
10123 #endif
10124
10125 /*-----------------------------------------------------------------*/
10126 /* genrshOne - right shift a one byte quantity by known count      */
10127 /*-----------------------------------------------------------------*/
10128 static void genrshOne (operand *result, operand *left,
10129                        int shCount, int sign)
10130 {
10131     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10132     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10133 }
10134
10135 /*-----------------------------------------------------------------*/
10136 /* genrshTwo - right shift two bytes by known amount != 0          */
10137 /*-----------------------------------------------------------------*/
10138 static void genrshTwo (operand *result,operand *left,
10139                        int shCount, int sign)
10140 {
10141   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10142   /* if shCount >= 8 */
10143   if (shCount >= 8) {
10144     shCount -= 8 ;
10145     if (shCount)
10146       shiftR1Left2Result(left, MSB16, result, LSB,
10147                          shCount, sign);
10148     else
10149       movLeft2Result(left, MSB16, result, LSB);
10150
10151     pic16_addSign (result, 1, sign);
10152   }
10153
10154   /*  1 <= shCount <= 7 */
10155   else
10156     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10157 }
10158
10159 /*-----------------------------------------------------------------*/
10160 /* shiftRLong - shift right one long from left to result           */
10161 /* offl = LSB or MSB16                                             */
10162 /*-----------------------------------------------------------------*/
10163 static void shiftRLong (operand *left, int offl,
10164                         operand *result, int sign)
10165 {
10166     int size = AOP_SIZE(result);
10167     int same = pic16_sameRegs(AOP(left),AOP(result));
10168     int i;
10169     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10170
10171         if (same && (offl == MSB16)) { //shift one byte right
10172                 for(i=MSB16;i<size;i++) {
10173                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10174                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10175                 }
10176         }
10177
10178     if(sign)
10179                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10180         else
10181                 emitCLRC;
10182
10183         if (same) {
10184                 if (offl == LSB)
10185                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10186         } else {
10187         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10188         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10189         }
10190
10191     if(offl == MSB16) {
10192         /* add sign of "a" */
10193         pic16_addSign(result, MSB32, sign);
10194         }
10195
10196         if (same) {
10197         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10198         } else {
10199         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10200         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10201         }
10202         
10203         if (same) {
10204         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10205         } else {
10206         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10207         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10208         }
10209
10210         if (same) {
10211         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10212         } else {
10213         if(offl == LSB){
10214                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10215                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10216         }
10217         }
10218 }
10219
10220 /*-----------------------------------------------------------------*/
10221 /* genrshFour - shift four byte by a known amount != 0             */
10222 /*-----------------------------------------------------------------*/
10223 static void genrshFour (operand *result, operand *left,
10224                         int shCount, int sign)
10225 {
10226   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10227   /* if shifting more that 3 bytes */
10228   if(shCount >= 24 ) {
10229     shCount -= 24;
10230     if(shCount)
10231       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10232     else
10233       movLeft2Result(left, MSB32, result, LSB);
10234
10235     pic16_addSign(result, MSB16, sign);
10236   }
10237   else if(shCount >= 16){
10238     shCount -= 16;
10239     if(shCount)
10240       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10241     else{
10242       movLeft2Result(left, MSB24, result, LSB);
10243       movLeft2Result(left, MSB32, result, MSB16);
10244     }
10245     pic16_addSign(result, MSB24, sign);
10246   }
10247   else if(shCount >= 8){
10248     shCount -= 8;
10249     if(shCount == 1)
10250       shiftRLong(left, MSB16, result, sign);
10251     else if(shCount == 0){
10252       movLeft2Result(left, MSB16, result, LSB);
10253       movLeft2Result(left, MSB24, result, MSB16);
10254       movLeft2Result(left, MSB32, result, MSB24);
10255       pic16_addSign(result, MSB32, sign);
10256     }
10257     else{ //shcount >= 2
10258       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10259       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10260       /* the last shift is signed */
10261       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10262       pic16_addSign(result, MSB32, sign);
10263     }
10264   }
10265   else{   /* 1 <= shCount <= 7 */
10266     if(shCount <= 2){
10267       shiftRLong(left, LSB, result, sign);
10268       if(shCount == 2)
10269         shiftRLong(result, LSB, result, sign);
10270     }
10271     else{
10272       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10273       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10274       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10275     }
10276   }
10277 }
10278
10279 /*-----------------------------------------------------------------*/
10280 /* genRightShiftLiteral - right shifting by known count            */
10281 /*-----------------------------------------------------------------*/
10282 static void genRightShiftLiteral (operand *left,
10283                                   operand *right,
10284                                   operand *result,
10285                                   iCode *ic,
10286                                   int sign)
10287 {    
10288   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10289   int lsize,res_size;
10290
10291   pic16_freeAsmop(right,NULL,ic,TRUE);
10292
10293   pic16_aopOp(left,ic,FALSE);
10294   pic16_aopOp(result,ic,TRUE);
10295
10296   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10297
10298 #if VIEW_SIZE
10299   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10300                  AOP_SIZE(left));
10301 #endif
10302
10303   lsize = pic16_getDataSize(left);
10304   res_size = pic16_getDataSize(result);
10305   /* test the LEFT size !!! */
10306
10307   /* I suppose that the left size >= result size */
10308   if(shCount == 0){
10309     assert (res_size <= lsize);
10310     while (res_size--) {
10311       pic16_mov2f (AOP(result), AOP(left), res_size);
10312     } // for
10313   }
10314
10315   else if(shCount >= (lsize * 8)){
10316
10317     if(res_size == 1) {
10318       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10319       if(sign) {
10320         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10321         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10322       }
10323     } else {
10324
10325       if(sign) {
10326         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10327         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10328         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10329         while(res_size--)
10330           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10331
10332       } else {
10333
10334         while(res_size--)
10335           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10336       }
10337     }
10338   } else {
10339
10340     switch (res_size) {
10341     case 1:
10342       genrshOne (result,left,shCount,sign);
10343       break;
10344
10345     case 2:
10346       genrshTwo (result,left,shCount,sign);
10347       break;
10348
10349     case 4:
10350       genrshFour (result,left,shCount,sign);
10351       break;
10352     default :
10353       break;
10354     }
10355
10356   }
10357
10358   pic16_freeAsmop(left,NULL,ic,TRUE);
10359   pic16_freeAsmop(result,NULL,ic,TRUE);
10360 }
10361
10362 #if !(USE_GENERIC_SIGNED_SHIFT)
10363 /*-----------------------------------------------------------------*/
10364 /* genSignedRightShift - right shift of signed number              */
10365 /*-----------------------------------------------------------------*/
10366 static void genSignedRightShift (iCode *ic)
10367 {
10368   operand *right, *left, *result;
10369   int size, offset;
10370   //  char *l;
10371   symbol *tlbl, *tlbl1 ;
10372   pCodeOp *pctemp;
10373
10374   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10375
10376   /* we do it the hard way put the shift count in b
10377      and loop thru preserving the sign */
10378   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10379
10380   right = IC_RIGHT(ic);
10381   left  = IC_LEFT(ic);
10382   result = IC_RESULT(ic);
10383
10384   pic16_aopOp(right,ic,FALSE);  
10385   pic16_aopOp(left,ic,FALSE);
10386   pic16_aopOp(result,ic,FALSE);
10387
10388
10389   if ( AOP_TYPE(right) == AOP_LIT) {
10390     genRightShiftLiteral (left,right,result,ic,1);
10391     return ;
10392   }
10393   /* shift count is unknown then we have to form 
10394      a loop get the loop count in B : Note: we take
10395      only the lower order byte since shifting
10396      more that 32 bits make no sense anyway, ( the
10397      largest size of an object can be only 32 bits ) */  
10398
10399   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10400   //pic16_emitcode("inc","b");
10401   //pic16_freeAsmop (right,NULL,ic,TRUE);
10402   //pic16_aopOp(left,ic,FALSE);
10403   //pic16_aopOp(result,ic,FALSE);
10404
10405   /* now move the left to the result if they are not the
10406      same */
10407   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10408       AOP_SIZE(result) > 1) {
10409
10410     size = AOP_SIZE(result);
10411     offset=0;
10412     while (size--) { 
10413       /*
10414         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10415         if (*l == '@' && IS_AOP_PREG(result)) {
10416
10417         pic16_emitcode("mov","a,%s",l);
10418         pic16_aopPut(AOP(result),"a",offset);
10419         } else
10420         pic16_aopPut(AOP(result),l,offset);
10421       */
10422       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10423       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10424
10425       offset++;
10426     }
10427   }
10428
10429   /* mov the highest order bit to OVR */    
10430   tlbl = newiTempLabel(NULL);
10431   tlbl1= newiTempLabel(NULL);
10432
10433   size = AOP_SIZE(result);
10434   offset = size - 1;
10435
10436   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10437
10438   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10439
10440   /* offset should be 0, 1 or 3 */
10441   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10442   emitSKPNZ;
10443   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10444
10445   pic16_emitpcode(POC_MOVWF, pctemp);
10446
10447
10448   pic16_emitpLabel(tlbl->key);
10449
10450   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10451   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10452
10453   while(--size) {
10454     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10455   }
10456
10457   pic16_emitpcode(POC_DECFSZ,  pctemp);
10458   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10459   pic16_emitpLabel(tlbl1->key);
10460
10461   pic16_popReleaseTempReg(pctemp,1);
10462 #if 0
10463   size = AOP_SIZE(result);
10464   offset = size - 1;
10465   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10466   pic16_emitcode("rlc","a");
10467   pic16_emitcode("mov","ov,c");
10468   /* if it is only one byte then */
10469   if (size == 1) {
10470     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10471     MOVA(l);
10472     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10473     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10474     pic16_emitcode("mov","c,ov");
10475     pic16_emitcode("rrc","a");
10476     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10477     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10478     pic16_aopPut(AOP(result),"a",0);
10479     goto release ;
10480   }
10481
10482   reAdjustPreg(AOP(result));
10483   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10484   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10485   pic16_emitcode("mov","c,ov");
10486   while (size--) {
10487     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10488     MOVA(l);
10489     pic16_emitcode("rrc","a");         
10490     pic16_aopPut(AOP(result),"a",offset--);
10491   }
10492   reAdjustPreg(AOP(result));
10493   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10494   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10495
10496  release:
10497 #endif
10498
10499   pic16_freeAsmop(left,NULL,ic,TRUE);
10500   pic16_freeAsmop(result,NULL,ic,TRUE);
10501   pic16_freeAsmop(right,NULL,ic,TRUE);
10502 }
10503 #endif
10504
10505 #if !(USE_GENERIC_SIGNED_SHIFT)
10506 #warning This implementation of genRightShift() is incomplete!
10507 /*-----------------------------------------------------------------*/
10508 /* genRightShift - generate code for right shifting                */
10509 /*-----------------------------------------------------------------*/
10510 static void genRightShift (iCode *ic)
10511 {
10512     operand *right, *left, *result;
10513     sym_link *letype ;
10514     int size, offset;
10515     char *l;
10516     symbol *tlbl, *tlbl1 ;
10517
10518     /* if signed then we do it the hard way preserve the
10519     sign bit moving it inwards */
10520     letype = getSpec(operandType(IC_LEFT(ic)));
10521     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10522
10523     if (!SPEC_USIGN(letype)) {
10524         genSignedRightShift (ic);
10525         return ;
10526     }
10527
10528     /* signed & unsigned types are treated the same : i.e. the
10529     signed is NOT propagated inwards : quoting from the
10530     ANSI - standard : "for E1 >> E2, is equivalent to division
10531     by 2**E2 if unsigned or if it has a non-negative value,
10532     otherwise the result is implementation defined ", MY definition
10533     is that the sign does not get propagated */
10534
10535     right = IC_RIGHT(ic);
10536     left  = IC_LEFT(ic);
10537     result = IC_RESULT(ic);
10538
10539     pic16_aopOp(right,ic,FALSE);
10540
10541     /* if the shift count is known then do it 
10542     as efficiently as possible */
10543     if (AOP_TYPE(right) == AOP_LIT) {
10544         genRightShiftLiteral (left,right,result,ic, 0);
10545         return ;
10546     }
10547
10548     /* shift count is unknown then we have to form 
10549     a loop get the loop count in B : Note: we take
10550     only the lower order byte since shifting
10551     more that 32 bits make no sense anyway, ( the
10552     largest size of an object can be only 32 bits ) */  
10553
10554     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10555     pic16_emitcode("inc","b");
10556     pic16_aopOp(left,ic,FALSE);
10557     pic16_aopOp(result,ic,FALSE);
10558
10559     /* now move the left to the result if they are not the
10560     same */
10561     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10562         AOP_SIZE(result) > 1) {
10563
10564         size = AOP_SIZE(result);
10565         offset=0;
10566         while (size--) {
10567             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10568             if (*l == '@' && IS_AOP_PREG(result)) {
10569
10570                 pic16_emitcode("mov","a,%s",l);
10571                 pic16_aopPut(AOP(result),"a",offset);
10572             } else
10573                 pic16_aopPut(AOP(result),l,offset);
10574             offset++;
10575         }
10576     }
10577
10578     tlbl = newiTempLabel(NULL);
10579     tlbl1= newiTempLabel(NULL);
10580     size = AOP_SIZE(result);
10581     offset = size - 1;
10582
10583     /* if it is only one byte then */
10584     if (size == 1) {
10585
10586       tlbl = newiTempLabel(NULL);
10587       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10588         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10589         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10590       }
10591
10592       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10593       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10594       pic16_emitpLabel(tlbl->key);
10595       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10596       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10597       emitSKPC;
10598       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10599
10600       goto release ;
10601     }
10602
10603     reAdjustPreg(AOP(result));
10604     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10605     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10606     CLRC;
10607     while (size--) {
10608         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10609         MOVA(l);
10610         pic16_emitcode("rrc","a");         
10611         pic16_aopPut(AOP(result),"a",offset--);
10612     }
10613     reAdjustPreg(AOP(result));
10614
10615     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10616     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10617
10618 release:
10619     pic16_freeAsmop(left,NULL,ic,TRUE);
10620     pic16_freeAsmop (right,NULL,ic,TRUE);
10621     pic16_freeAsmop(result,NULL,ic,TRUE);
10622 }
10623 #endif
10624
10625 #if (USE_GENERIC_SIGNED_SHIFT)
10626 /*-----------------------------------------------------------------*/
10627 /* genGenericShift - generates code for left or right shifting     */
10628 /*-----------------------------------------------------------------*/
10629 static void genGenericShift (iCode *ic, int isShiftLeft) {
10630   operand *left,*right, *result;
10631   int offset;
10632   int sign, signedCount;
10633   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10634   PIC_OPCODE pos_shift, neg_shift;
10635
10636   FENTRY;
10637
10638   right = IC_RIGHT(ic);
10639   left  = IC_LEFT(ic);
10640   result = IC_RESULT(ic);
10641
10642   pic16_aopOp(right,ic,FALSE);
10643   pic16_aopOp(left,ic,FALSE);
10644   pic16_aopOp(result,ic,TRUE);
10645
10646   sign = !SPEC_USIGN(operandType (left));
10647   signedCount = !SPEC_USIGN(operandType (right));
10648
10649   /* if the shift count is known then do it 
10650      as efficiently as possible */
10651   if (AOP_TYPE(right) == AOP_LIT) {
10652     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10653     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10654     // we should modify right->aopu.aop_lit here!
10655     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10656     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10657     if (isShiftLeft)
10658       pic16_genLeftShiftLiteral (left,right,result,ic);
10659     else
10660       genRightShiftLiteral (left,right,result,ic, sign);
10661
10662     goto release;
10663   } // if (right is literal)
10664
10665   /* shift count is unknown then we have to form a loop.
10666    * Note: we take only the lower order byte since shifting
10667    * more than 32 bits make no sense anyway, ( the
10668    * largest size of an object can be only 32 bits )
10669    * Note: we perform arithmetic shifts if the left operand is
10670    * signed and we do an (effective) right shift, i. e. we
10671    * shift in the sign bit from the left. */
10672    
10673   label_complete = newiTempLabel ( NULL );
10674   label_loop_pos = newiTempLabel ( NULL );
10675   label_loop_neg = NULL;
10676   label_negative = NULL;
10677   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10678   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10679
10680   if (signedCount) {
10681     // additional labels needed
10682     label_loop_neg = newiTempLabel ( NULL );
10683     label_negative = newiTempLabel ( NULL );
10684   } // if
10685
10686   // copy source to result -- this will effectively truncate the left operand to the size of result!
10687   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10688   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10689   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10690     pic16_mov2f (AOP(result),AOP(left), offset);
10691   } // for
10692
10693   // if result is longer than left, fill with zeros (or sign)
10694   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10695     if (sign && AOP_SIZE(left) > 0) {
10696       // shift signed operand -- fill with sign
10697       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10698       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10699       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10700       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10701         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10702       } // for
10703     } else {
10704       // shift unsigned operand -- fill result with zeros
10705       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10706         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10707       } // for
10708     }
10709   } // if (size mismatch)
10710
10711   pic16_mov2w (AOP(right), 0);
10712   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10713   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10714   
10715 #if 0
10716   // perform a shift by one (shift count is positive)
10717   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10718   // 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])
10719   pic16_emitpLabel (label_loop_pos->key);
10720   emitCLRC;
10721   if (sign && (pos_shift == POC_RRCF)) {
10722     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10723     emitSETC;
10724   } // if
10725   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10726   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10727   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10728 #else
10729   // perform a shift by one (shift count is positive)
10730   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10731   // 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])
10732   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10733   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10734   emitCLRC;
10735   pic16_emitpLabel (label_loop_pos->key);
10736   if (sign && (pos_shift == POC_RRCF)) {
10737     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10738     emitSETC;
10739   } // if
10740   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10741   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10742   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10743   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10744 #endif
10745
10746   if (signedCount) {
10747     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10748
10749     pic16_emitpLabel (label_negative->key);
10750     // perform a shift by -1 (shift count is negative)
10751     // 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)
10752     emitCLRC;
10753     pic16_emitpLabel (label_loop_neg->key);
10754     if (sign && (neg_shift == POC_RRCF)) {
10755       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10756       emitSETC;
10757     } // if
10758     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10759     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10760     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10761     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10762   } // if (signedCount)
10763
10764   pic16_emitpLabel (label_complete->key);
10765
10766 release:
10767   pic16_freeAsmop (right,NULL,ic,TRUE);
10768   pic16_freeAsmop(left,NULL,ic,TRUE);
10769   pic16_freeAsmop(result,NULL,ic,TRUE);
10770 }
10771
10772 static void genLeftShift (iCode *ic) {
10773   genGenericShift (ic, 1);
10774 }
10775
10776 static void genRightShift (iCode *ic) {
10777   genGenericShift (ic, 0);
10778 }
10779 #endif
10780
10781
10782 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10783 void pic16_loadFSR0(operand *op, int lit)
10784 {
10785   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10786     if (AOP_TYPE(op) == AOP_LIT) {
10787       /* handle 12 bit integers correctly */
10788       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10789       if ((val & 0x0fff) != val) {
10790         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10791                 val, (val & 0x0fff) );
10792         val &= 0x0fff;
10793       }
10794       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10795     } else {
10796       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10797     }
10798   } else {
10799     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10800     // set up FSR0 with address of result
10801     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10802     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10803   }
10804 }
10805
10806 /*----------------------------------------------------------------*/
10807 /* pic16_derefPtr - move one byte from the location ptr points to */
10808 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10809 /*                  to the location ptr points to (doWrite != 0)   */
10810 /*----------------------------------------------------------------*/
10811 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10812 {
10813   if (!IS_PTR(operandType(ptr)))
10814   {
10815     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10816     else pic16_mov2w (AOP(ptr), 0);
10817     return;
10818   }
10819
10820   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10821   /* We might determine pointer type right here: */
10822   p_type = DCL_TYPE(operandType(ptr));
10823
10824   switch (p_type) {
10825     case FPOINTER:
10826     case POINTER:
10827       if (!fsr0_setup || !*fsr0_setup)
10828       {
10829         pic16_loadFSR0( ptr, 0 );
10830         if (fsr0_setup) *fsr0_setup = 1;
10831       }
10832       if (doWrite)
10833         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10834       else
10835         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10836       break;
10837
10838     case GPOINTER:
10839       if (AOP(ptr)->aopu.aop_reg[2]) {
10840         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10841         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10842         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10843         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10844         pic16_mov2w(AOP(ptr), 2);
10845         pic16_callGenericPointerRW(doWrite, 1);
10846       } else {
10847         // data pointer (just 2 byte given)
10848         if (!fsr0_setup || !*fsr0_setup)
10849         {
10850           pic16_loadFSR0( ptr, 0 );
10851           if (fsr0_setup) *fsr0_setup = 1;
10852         }
10853         if (doWrite)
10854           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10855         else
10856           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10857       }
10858       break;
10859
10860     default:
10861       assert (0 && "invalid pointer type specified");
10862       break;
10863   }
10864 }
10865
10866 /*-----------------------------------------------------------------*/
10867 /* genUnpackBits - generates code for unpacking bits               */
10868 /*-----------------------------------------------------------------*/
10869 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10870 {    
10871   int shCnt ;
10872   sym_link *etype, *letype;
10873   int blen=0, bstr=0;
10874   int lbstr;
10875   int same;
10876   pCodeOp *op;
10877
10878   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10879   etype = getSpec(operandType(result));
10880   letype = getSpec(operandType(left));
10881
10882   //    if(IS_BITFIELD(etype)) {
10883   blen = SPEC_BLEN(etype);
10884   bstr = SPEC_BSTR(etype);
10885   //    }
10886
10887   lbstr = SPEC_BSTR( letype );
10888
10889   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10890       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10891
10892 #if 1
10893   if((blen == 1) && (bstr < 8)
10894       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10895     /* it is a single bit, so use the appropriate bit instructions */
10896     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10897
10898     same = pic16_sameRegs(AOP(left),AOP(result));
10899     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10900     pic16_emitpcode(POC_CLRF, op);
10901
10902     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10903       /* workaround to reduce the extra lfsr instruction */
10904       pic16_emitpcode(POC_BTFSC,
10905           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10906     } else {
10907       assert (PIC_IS_DATA_PTR (operandType(left)));
10908       pic16_loadFSR0 (left, 0);
10909       pic16_emitpcode(POC_BTFSC,
10910           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10911     }
10912
10913     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10914       /* unsigned bitfields result in either 0 or 1 */
10915       pic16_emitpcode(POC_INCF, op);
10916     } else {
10917       /* signed bitfields result in either 0 or -1 */
10918       pic16_emitpcode(POC_DECF, op);
10919     }
10920     if (same) {
10921       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10922     }
10923
10924     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10925     return;
10926   }
10927
10928 #endif
10929
10930   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10931     // access symbol directly
10932     pic16_mov2w (AOP(left), 0);
10933   } else {
10934     pic16_derefPtr (left, ptype, 0, NULL);
10935   }
10936
10937   /* if we have bitdisplacement then it fits   */
10938   /* into this byte completely or if length is */
10939   /* less than a byte                          */
10940   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10941
10942     /* shift right acc */
10943     AccRsh(shCnt, 0);
10944
10945     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10946           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10947
10948     /* VR -- normally I would use the following, but since we use the hack,
10949      * to avoid the masking from AccRsh, why not mask it right now? */
10950
10951     /*
10952        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10953      */
10954
10955     /* extend signed bitfields to 8 bits */
10956     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10957     {
10958       assert (blen + bstr > 0);
10959       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10960       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10961     }
10962
10963     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10964
10965     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10966     return ;
10967   }
10968
10969   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10970   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10971   exit(EXIT_FAILURE);
10972
10973   return ;
10974 }
10975
10976
10977 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10978 {
10979   int size, offset = 0, leoffset=0 ;
10980
10981         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10982         pic16_aopOp(result, ic, TRUE);
10983
10984         FENTRY;
10985
10986         size = AOP_SIZE(result);
10987 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10988
10989
10990 #if 1
10991         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10992                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10993                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10994                 goto release;
10995         }
10996 #endif
10997
10998         if(AOP(left)->aopu.pcop->type == PO_DIR)
10999                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11000
11001         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11002
11003         while (size--) {
11004                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11005                 
11006 //              pic16_DumpOp("(result)",result);
11007                 if(is_LitAOp(AOP(result))) {
11008                         pic16_mov2w(AOP(left), offset); // patch 8
11009                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11010                 } else {
11011                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11012                                 pic16_popGet(AOP(left), offset), //patch 8
11013                                 pic16_popGet(AOP(result), offset)));
11014                 }
11015
11016                 offset++;
11017                 leoffset++;
11018         }
11019
11020 release:
11021     pic16_freeAsmop(result,NULL,ic,TRUE);
11022 }
11023
11024
11025
11026 /*-----------------------------------------------------------------*/
11027 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11028 /*-----------------------------------------------------------------*/
11029 static void genNearPointerGet (operand *left, 
11030                                operand *result, 
11031                                iCode *ic)
11032 {
11033 //  asmop *aop = NULL;
11034   //regs *preg = NULL ;
11035   sym_link *rtype, *retype;
11036   sym_link *ltype, *letype;
11037
11038     FENTRY;
11039     
11040     rtype = operandType(result);
11041     retype= getSpec(rtype);
11042     ltype = operandType(left);
11043     letype= getSpec(ltype);
11044     
11045     pic16_aopOp(left,ic,FALSE);
11046
11047 //    pic16_DumpOp("(left)",left);
11048 //    pic16_DumpOp("(result)",result);
11049
11050     /* if left is rematerialisable and
11051      * result is not bit variable type and
11052      * the left is pointer to data space i.e
11053      * lower 128 bytes of space */
11054     
11055     if (AOP_TYPE(left) == AOP_PCODE
11056       && !IS_BITFIELD(retype)
11057       && DCL_TYPE(ltype) == POINTER) {
11058
11059         genDataPointerGet (left,result,ic);
11060         pic16_freeAsmop(left, NULL, ic, TRUE);
11061         return ;
11062     }
11063     
11064     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11065     pic16_aopOp (result,ic,TRUE);
11066     
11067     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11068
11069 #if 1
11070     if(IS_BITFIELD( retype )
11071       && (SPEC_BLEN(operandType(result))==1)
11072     ) {
11073       iCode *nextic;
11074       pCodeOp *jop;
11075       int bitstrt, bytestrt;
11076
11077         /* if this is bitfield of size 1, see if we are checking the value
11078          * of a single bit in an if-statement,
11079          * if yes, then don't generate usual code, but execute the
11080          * genIfx directly -- VR */
11081
11082         nextic = ic->next;
11083
11084         /* CHECK: if next iCode is IFX
11085          * and current result operand is nextic's conditional operand
11086          * and current result operand live ranges ends at nextic's key number
11087          */
11088         if((nextic->op == IFX)
11089           && (result == IC_COND(nextic))
11090           && (OP_LIVETO(result) == nextic->seq)
11091           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11092           ) {
11093             /* everything is ok then */
11094             /* find a way to optimize the genIfx iCode */
11095
11096             bytestrt = SPEC_BSTR(operandType(result))/8;
11097             bitstrt = SPEC_BSTR(operandType(result))%8;
11098             
11099             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11100
11101             genIfxpCOpJump(nextic, jop);
11102             
11103             pic16_freeAsmop(left, NULL, ic, TRUE);
11104             pic16_freeAsmop(result, NULL, ic, TRUE);
11105             return;
11106         }
11107     }
11108 #endif
11109
11110     /* if bitfield then unpack the bits */
11111     if (IS_BITFIELD(letype)) 
11112       genUnpackBits (result, left, NULL, POINTER);
11113     else {
11114       /* we have can just get the values */
11115       int size = AOP_SIZE(result);
11116       int offset = 0;   
11117         
11118       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11119
11120       pic16_loadFSR0( left, 0 );
11121
11122       while(size--) {
11123         if(size) {
11124           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11125                 pic16_popGet(AOP(result), offset++)));
11126         } else {
11127           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11128                 pic16_popGet(AOP(result), offset++)));
11129         }
11130       }
11131     }
11132
11133 #if 0
11134     /* now some housekeeping stuff */
11135     if (aop) {
11136       /* we had to allocate for this iCode */
11137       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11138       pic16_freeAsmop(NULL,aop,ic,TRUE);
11139     } else { 
11140       /* we did not allocate which means left
11141        * already in a pointer register, then
11142        * if size > 0 && this could be used again
11143        * we have to point it back to where it 
11144        * belongs */
11145       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11146       if (AOP_SIZE(result) > 1
11147         && !OP_SYMBOL(left)->remat
11148         && ( OP_SYMBOL(left)->liveTo > ic->seq
11149             || ic->depth )) {
11150 //        int size = AOP_SIZE(result) - 1;
11151 //        while (size--)
11152 //          pic16_emitcode("dec","%s",rname);
11153         }
11154     }
11155 #endif
11156
11157     /* done */
11158     pic16_freeAsmop(left,NULL,ic,TRUE);
11159     pic16_freeAsmop(result,NULL,ic,TRUE);
11160 }
11161
11162 /*-----------------------------------------------------------------*/
11163 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11164 /*-----------------------------------------------------------------*/
11165 static void genPagedPointerGet (operand *left, 
11166                                operand *result, 
11167                                iCode *ic)
11168 {
11169     asmop *aop = NULL;
11170     regs *preg = NULL ;
11171     char *rname ;
11172     sym_link *rtype, *retype;    
11173
11174     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11175
11176     rtype = operandType(result);
11177     retype= getSpec(rtype);
11178     
11179     pic16_aopOp(left,ic,FALSE);
11180
11181   /* if the value is already in a pointer register
11182        then don't need anything more */
11183     if (!AOP_INPREG(AOP(left))) {
11184         /* otherwise get a free pointer register */
11185         aop = newAsmop(0);
11186         preg = getFreePtr(ic,&aop,FALSE);
11187         pic16_emitcode("mov","%s,%s",
11188                 preg->name,
11189                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11190         rname = preg->name ;
11191     } else
11192         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11193     
11194     pic16_freeAsmop(left,NULL,ic,TRUE);
11195     pic16_aopOp (result,ic,TRUE);
11196
11197     /* if bitfield then unpack the bits */
11198     if (IS_BITFIELD(retype)) 
11199         genUnpackBits (result,left,rname,PPOINTER);
11200     else {
11201         /* we have can just get the values */
11202         int size = AOP_SIZE(result);
11203         int offset = 0 ;        
11204         
11205         while (size--) {
11206             
11207             pic16_emitcode("movx","a,@%s",rname);
11208             pic16_aopPut(AOP(result),"a",offset);
11209             
11210             offset++ ;
11211             
11212             if (size)
11213                 pic16_emitcode("inc","%s",rname);
11214         }
11215     }
11216
11217     /* now some housekeeping stuff */
11218     if (aop) {
11219         /* we had to allocate for this iCode */
11220         pic16_freeAsmop(NULL,aop,ic,TRUE);
11221     } else { 
11222         /* we did not allocate which means left
11223            already in a pointer register, then
11224            if size > 0 && this could be used again
11225            we have to point it back to where it 
11226            belongs */
11227         if (AOP_SIZE(result) > 1 &&
11228             !OP_SYMBOL(left)->remat &&
11229             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11230               ic->depth )) {
11231             int size = AOP_SIZE(result) - 1;
11232             while (size--)
11233                 pic16_emitcode("dec","%s",rname);
11234         }
11235     }
11236
11237     /* done */
11238     pic16_freeAsmop(result,NULL,ic,TRUE);
11239     
11240         
11241 }
11242
11243 #if 0
11244 /* This code is not adjusted to PIC16 and fails utterly.
11245  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11246
11247 /*-----------------------------------------------------------------*/
11248 /* genFarPointerGet - gget value from far space                    */
11249 /*-----------------------------------------------------------------*/
11250 static void genFarPointerGet (operand *left,
11251                               operand *result, iCode *ic)
11252 {
11253     int size, offset ;
11254     sym_link *retype = getSpec(operandType(result));
11255
11256     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11257
11258     pic16_aopOp(left,ic,FALSE);
11259
11260     /* if the operand is already in dptr 
11261     then we do nothing else we move the value to dptr */
11262     if (AOP_TYPE(left) != AOP_STR) {
11263         /* if this is remateriazable */
11264         if (AOP_TYPE(left) == AOP_IMMD)
11265             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11266         else { /* we need to get it byte by byte */
11267             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11268             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11269             if (options.model == MODEL_FLAT24)
11270             {
11271                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11272             }
11273         }
11274     }
11275     /* so dptr know contains the address */
11276     pic16_freeAsmop(left,NULL,ic,TRUE);
11277     pic16_aopOp(result,ic,TRUE);
11278
11279     /* if bit then unpack */
11280     if (IS_BITFIELD(retype)) 
11281         genUnpackBits(result,left,"dptr",FPOINTER);
11282     else {
11283         size = AOP_SIZE(result);
11284         offset = 0 ;
11285
11286         while (size--) {
11287             pic16_emitcode("movx","a,@dptr");
11288             pic16_aopPut(AOP(result),"a",offset++);
11289             if (size)
11290                 pic16_emitcode("inc","dptr");
11291         }
11292     }
11293
11294     pic16_freeAsmop(result,NULL,ic,TRUE);
11295 }
11296 #endif
11297
11298 #if 0
11299 /*-----------------------------------------------------------------*/
11300 /* genCodePointerGet - get value from code space                  */
11301 /*-----------------------------------------------------------------*/
11302 static void genCodePointerGet (operand *left,
11303                                 operand *result, iCode *ic)
11304 {
11305     int size, offset ;
11306     sym_link *retype = getSpec(operandType(result));
11307
11308     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11309
11310     pic16_aopOp(left,ic,FALSE);
11311
11312     /* if the operand is already in dptr 
11313     then we do nothing else we move the value to dptr */
11314     if (AOP_TYPE(left) != AOP_STR) {
11315         /* if this is remateriazable */
11316         if (AOP_TYPE(left) == AOP_IMMD)
11317             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11318         else { /* we need to get it byte by byte */
11319             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11320             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11321             if (options.model == MODEL_FLAT24)
11322             {
11323                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11324             }
11325         }
11326     }
11327     /* so dptr know contains the address */
11328     pic16_freeAsmop(left,NULL,ic,TRUE);
11329     pic16_aopOp(result,ic,FALSE);
11330
11331     /* if bit then unpack */
11332     if (IS_BITFIELD(retype)) 
11333         genUnpackBits(result,left,"dptr",CPOINTER);
11334     else {
11335         size = AOP_SIZE(result);
11336         offset = 0 ;
11337
11338         while (size--) {
11339             pic16_emitcode("clr","a");
11340             pic16_emitcode("movc","a,@a+dptr");
11341             pic16_aopPut(AOP(result),"a",offset++);
11342             if (size)
11343                 pic16_emitcode("inc","dptr");
11344         }
11345     }
11346
11347     pic16_freeAsmop(result,NULL,ic,TRUE);
11348 }
11349 #endif
11350
11351 #if 0
11352 /*-----------------------------------------------------------------*/
11353 /* genGenPointerGet - gget value from generic pointer space        */
11354 /*-----------------------------------------------------------------*/
11355 static void genGenPointerGet (operand *left,
11356                               operand *result, iCode *ic)
11357 {
11358   int size, offset, lit;
11359   sym_link *retype = getSpec(operandType(result));
11360
11361         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11362         pic16_aopOp(left,ic,FALSE);
11363         pic16_aopOp(result,ic,FALSE);
11364         size = AOP_SIZE(result);
11365
11366         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11367
11368         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11369
11370                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11371                 // load FSR0 from immediate
11372                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11373
11374 //              pic16_loadFSR0( left );
11375
11376                 offset = 0;
11377                 while(size--) {
11378                         if(size) {
11379                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11380                         } else {
11381                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11382                         }
11383                         offset++;
11384                 }
11385                 goto release;
11386
11387         }
11388         else { /* we need to get it byte by byte */
11389                 // set up FSR0 with address from left
11390                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11391                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11392                 
11393                 offset = 0 ;
11394
11395                 while(size--) {
11396                         if(size) {
11397                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11398                         } else {
11399                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11400                         }
11401                         offset++;
11402                 }
11403                 goto release;
11404         }
11405
11406   /* if bit then unpack */
11407         if (IS_BITFIELD(retype)) 
11408                 genUnpackBits(result,left,"BAD",GPOINTER);
11409
11410         release:
11411         pic16_freeAsmop(left,NULL,ic,TRUE);
11412         pic16_freeAsmop(result,NULL,ic,TRUE);
11413
11414 }
11415 #endif
11416
11417
11418 /*-----------------------------------------------------------------*/
11419 /* genGenPointerGet - gget value from generic pointer space        */
11420 /*-----------------------------------------------------------------*/
11421 static void genGenPointerGet (operand *left,
11422                               operand *result, iCode *ic)
11423 {
11424   int size, offset, lit;
11425   sym_link *letype = getSpec(operandType(left));
11426
11427     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11428     pic16_aopOp(left,ic,FALSE);
11429     pic16_aopOp(result,ic,TRUE);
11430     size = AOP_SIZE(result);
11431
11432     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11433   
11434     /* if bit then unpack */
11435     if (IS_BITFIELD(letype)) {
11436       genUnpackBits(result,left,"BAD",GPOINTER);
11437       goto release;
11438     }
11439
11440     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11441
11442       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11443       // load FSR0 from immediate
11444       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11445
11446       werror(W_POSSBUG2, __FILE__, __LINE__);
11447
11448       offset = 0;
11449       while(size--) {
11450         if(size) {
11451           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11452         } else {
11453           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11454         }
11455         offset++;
11456       }
11457
11458       goto release;
11459
11460     } else { /* we need to get it byte by byte */
11461
11462       /* set up WREG:PRODL:FSR0L with address from left */
11463       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11464       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11465       pic16_mov2w(AOP(left), 2);
11466       pic16_callGenericPointerRW(0, size);
11467       
11468       assignResultValue(result, size, 1);
11469       
11470       goto release;
11471     }
11472
11473 release:
11474   pic16_freeAsmop(left,NULL,ic,TRUE);
11475   pic16_freeAsmop(result,NULL,ic,TRUE);
11476 }
11477
11478 /*-----------------------------------------------------------------*/
11479 /* genConstPointerGet - get value from const generic pointer space */
11480 /*-----------------------------------------------------------------*/
11481 static void genConstPointerGet (operand *left,
11482                                 operand *result, iCode *ic)
11483 {
11484   //sym_link *retype = getSpec(operandType(result));
11485   // symbol *albl = newiTempLabel(NULL);        // patch 15
11486   // symbol *blbl = newiTempLabel(NULL);        //
11487   // PIC_OPCODE poc;                            // patch 15
11488   int size;
11489   int offset = 0;
11490
11491   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11492   pic16_aopOp(left,ic,FALSE);
11493   pic16_aopOp(result,ic,TRUE);
11494   size = AOP_SIZE(result);
11495
11496   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11497
11498   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11499
11500   // set up table pointer
11501   if( (AOP_TYPE(left) == AOP_PCODE) 
11502       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11503           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11504     {
11505       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11506       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11507       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11508       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11509       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11510       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11511   } else {
11512     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11513     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11514     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11515   }
11516
11517   while(size--) {
11518     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11519     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11520     offset++;
11521   }
11522     
11523   pic16_freeAsmop(left,NULL,ic,TRUE);
11524   pic16_freeAsmop(result,NULL,ic,TRUE);
11525 }
11526
11527
11528 /*-----------------------------------------------------------------*/
11529 /* genPointerGet - generate code for pointer get                   */
11530 /*-----------------------------------------------------------------*/
11531 static void genPointerGet (iCode *ic)
11532 {
11533   operand *left, *result ;
11534   sym_link *type, *etype;
11535   int p_type;
11536
11537     FENTRY;
11538     
11539     left = IC_LEFT(ic);
11540     result = IC_RESULT(ic) ;
11541
11542     /* depending on the type of pointer we need to
11543     move it to the correct pointer register */
11544     type = operandType(left);
11545     etype = getSpec(type);
11546
11547 #if 0
11548     if (IS_PTR_CONST(type))
11549 #else
11550     if (IS_CODEPTR(type))
11551 #endif
11552       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11553
11554     /* if left is of type of pointer then it is simple */
11555     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11556       p_type = DCL_TYPE(type);
11557     else {
11558       /* we have to go by the storage class */
11559       p_type = PTR_TYPE(SPEC_OCLS(etype));
11560
11561       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11562
11563       if (SPEC_OCLS(etype)->codesp ) {
11564         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11565         //p_type = CPOINTER ;   
11566       } else
11567       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11568         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11569         /*p_type = FPOINTER ;*/ 
11570       } else
11571       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11572         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11573         /* p_type = PPOINTER; */
11574       } else
11575       if (SPEC_OCLS(etype) == idata ) {
11576         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11577         /* p_type = IPOINTER; */
11578       } else {
11579         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11580         /* p_type = POINTER ; */
11581       }
11582     }
11583
11584     /* now that we have the pointer type we assign
11585     the pointer values */
11586     switch (p_type) {
11587       case POINTER:     
11588       case FPOINTER:
11589       case IPOINTER:
11590         genNearPointerGet (left,result,ic);
11591         break;
11592
11593       case PPOINTER:
11594         genPagedPointerGet(left,result,ic);
11595         break;
11596
11597 #if 0
11598       /* PICs do not support FAR pointers... */
11599       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11600       case FPOINTER:
11601         genFarPointerGet (left,result,ic);
11602         break;
11603 #endif
11604
11605       case CPOINTER:
11606         genConstPointerGet (left,result,ic);
11607         //pic16_emitcodePointerGet (left,result,ic);
11608         break;
11609
11610       case GPOINTER:
11611 #if 0
11612       if (IS_PTR_CONST(type))
11613         genConstPointerGet (left,result,ic);
11614       else
11615 #endif
11616         genGenPointerGet (left,result,ic);
11617       break;
11618
11619     default:
11620       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11621               "genPointerGet: illegal pointer type");
11622     
11623     }
11624 }
11625
11626 /*-----------------------------------------------------------------*/
11627 /* genPackBits - generates code for packed bit storage             */
11628 /*-----------------------------------------------------------------*/
11629 static void genPackBits (sym_link    *etype , operand *result,
11630                          operand *right ,
11631                          char *rname, int p_type)
11632 {
11633   int shCnt = 0 ;
11634   int offset = 0  ;
11635   int rLen = 0 ;
11636   int blen, bstr ;   
11637   int shifted_and_masked = 0;
11638   unsigned long lit = (unsigned long)-1;
11639   sym_link *retype;
11640
11641   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11642   blen = SPEC_BLEN(etype);
11643   bstr = SPEC_BSTR(etype);
11644
11645   retype = getSpec(operandType(right));
11646
11647   if(AOP_TYPE(right) == AOP_LIT) {
11648     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11649     
11650     if((blen == 1) && (bstr < 8)) {
11651       /* it is a single bit, so use the appropriate bit instructions */
11652
11653       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11654
11655       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11656         /* workaround to reduce the extra lfsr instruction */
11657         if(lit) {
11658           pic16_emitpcode(POC_BSF,
11659               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11660         } else {
11661           pic16_emitpcode(POC_BCF,
11662               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11663         }
11664       } else {
11665         if (PIC_IS_DATA_PTR(operandType(result))) {
11666           pic16_loadFSR0(result, 0);
11667           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11668               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11669         } else {
11670           /* get old value */
11671           pic16_derefPtr (result, p_type, 0, NULL);
11672           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11673               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11674           /* write back new value */
11675           pic16_derefPtr (result, p_type, 1, NULL);
11676         }
11677       }
11678
11679       return;
11680     }
11681     /* IORLW below is more efficient */
11682     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11683     lit = (lit & ((1UL << blen) - 1)) << bstr;
11684     shifted_and_masked = 1;
11685     offset++;
11686   } else
11687     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11688         && IS_BITFIELD(retype) 
11689         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11690         && (blen == 1)) {
11691       int rblen, rbstr;
11692
11693       rblen = SPEC_BLEN( retype );
11694       rbstr = SPEC_BSTR( retype );
11695
11696       if(IS_BITFIELD(etype)) {
11697         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11698         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11699       } else {
11700         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11701       }
11702
11703       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11704
11705       if(IS_BITFIELD(etype)) {
11706         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11707       } else {
11708         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11709       }
11710
11711       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11712
11713       return;
11714     } else {
11715       /* move right to W */
11716       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11717     }
11718
11719   /* if the bit length is less than or   */
11720   /* it exactly fits a byte then         */
11721   if((shCnt=SPEC_BSTR(etype))
11722       || SPEC_BLEN(etype) <= 8 )  {
11723     int fsr0_setup = 0;
11724
11725     if (blen != 8 || bstr != 0) {
11726       // we need to combine the value with the old value
11727       if(!shifted_and_masked)
11728       {
11729         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11730
11731         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11732             SPEC_BSTR(etype), SPEC_BLEN(etype));
11733
11734         /* shift left acc, do NOT mask the result again */
11735         AccLsh(shCnt, 0);
11736
11737         /* using PRODH as a temporary register here */
11738         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11739       }
11740
11741       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11742         || IS_DIRECT(result)) {
11743         /* access symbol directly */
11744         pic16_mov2w (AOP(result), 0);
11745       } else {
11746         /* get old value */
11747         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11748       }
11749 #if 1
11750       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11751             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11752                             (unsigned char)(0xff >> (8-bstr))) ));
11753       if (!shifted_and_masked) {
11754         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11755       } else {
11756         /* We have the shifted and masked (literal) right value in `lit' */
11757         if (lit != 0)
11758           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11759       }
11760     } // if (blen != 8 || bstr != 0)
11761
11762     /* write new value back */
11763     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11764         || IS_DIRECT(result)) {
11765       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11766     } else {
11767       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11768     }
11769 #endif
11770
11771     return;
11772   }
11773
11774
11775 #if 0
11776   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11777   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11778   exit(EXIT_FAILURE);
11779 #endif
11780
11781
11782   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11783   rLen = SPEC_BLEN(etype)-8;
11784
11785   /* now generate for lengths greater than one byte */
11786   while (1) {
11787     rLen -= 8 ;
11788     if (rLen <= 0 ) {
11789       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11790       break ;
11791     }
11792
11793     switch (p_type) {
11794       case POINTER:
11795         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11796         break;
11797
11798         /*
11799            case FPOINTER:
11800            MOVA(l);
11801            pic16_emitcode("movx","@dptr,a");
11802            break;
11803
11804            case GPOINTER:
11805            MOVA(l);
11806            DEBUGpic16_emitcode(";lcall","__gptrput");
11807            break;  
11808          */
11809       default:
11810         assert(0);
11811     }   
11812
11813
11814     pic16_mov2w(AOP(right), offset++);
11815   }
11816
11817   /* last last was not complete */
11818   if (rLen)   {
11819     /* save the byte & read byte */
11820     switch (p_type) {
11821       case POINTER:
11822         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11823         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11824         break;
11825
11826         /*
11827            case FPOINTER:
11828            pic16_emitcode ("mov","b,a");
11829            pic16_emitcode("movx","a,@dptr");
11830            break;
11831
11832            case GPOINTER:
11833            pic16_emitcode ("push","b");
11834            pic16_emitcode ("push","acc");
11835            pic16_emitcode ("lcall","__gptrget");
11836            pic16_emitcode ("pop","b");
11837            break;
11838          */
11839       default:
11840         assert(0);
11841     }
11842     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11843     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11844     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11845     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11846     //        pic16_emitcode ("orl","a,b");
11847   }
11848
11849   //    if (p_type == GPOINTER)
11850   //        pic16_emitcode("pop","b");
11851
11852   switch (p_type) {
11853
11854     case POINTER:
11855       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11856       //        pic16_emitcode("mov","@%s,a",rname);
11857       break;
11858       /*
11859          case FPOINTER:
11860          pic16_emitcode("movx","@dptr,a");
11861          break;
11862
11863          case GPOINTER:
11864          DEBUGpic16_emitcode(";lcall","__gptrput");
11865          break;                 
11866        */
11867     default:
11868       assert(0);
11869   }
11870
11871   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11872 }
11873
11874 /*-----------------------------------------------------------------*/
11875 /* genDataPointerSet - remat pointer to data space                 */
11876 /*-----------------------------------------------------------------*/
11877 static void genDataPointerSet(operand *right,
11878                               operand *result,
11879                               iCode *ic)
11880 {
11881   int size, offset = 0, resoffset=0 ;
11882
11883     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11884     pic16_aopOp(right,ic,FALSE);
11885
11886     size = AOP_SIZE(right);
11887
11888 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11889
11890 #if 0
11891     if ( AOP_TYPE(result) == AOP_PCODE) {
11892       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11893               AOP(result)->aopu.pcop->name,
11894                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11895               PCOR(AOP(result)->aopu.pcop)->instance:
11896               PCOI(AOP(result)->aopu.pcop)->offset);
11897     }
11898 #endif
11899
11900     if(AOP(result)->aopu.pcop->type == PO_DIR)
11901       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11902
11903     while (size--) {
11904       if (AOP_TYPE(right) == AOP_LIT) {
11905         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11906         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11907       } else {
11908         pic16_mov2w(AOP(right), offset);
11909         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11910       }
11911       offset++;
11912       resoffset++;
11913     }
11914
11915     pic16_freeAsmop(right,NULL,ic,TRUE);
11916 }
11917
11918
11919
11920 /*-----------------------------------------------------------------*/
11921 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11922 /*-----------------------------------------------------------------*/
11923 static void genNearPointerSet (operand *right,
11924                                operand *result, 
11925                                iCode *ic)
11926 {
11927   asmop *aop = NULL;
11928   sym_link *retype;
11929   sym_link *ptype = operandType(result);
11930   sym_link *resetype;
11931     
11932     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11933     retype= getSpec(operandType(right));
11934     resetype = getSpec(operandType(result));
11935   
11936     pic16_aopOp(result,ic,FALSE);
11937     
11938     /* if the result is rematerializable &
11939      * in data space & not a bit variable */
11940         
11941     /* and result is not a bit variable */
11942     if (AOP_TYPE(result) == AOP_PCODE
11943 //      && AOP_TYPE(result) == AOP_IMMD
11944       && DCL_TYPE(ptype) == POINTER
11945       && !IS_BITFIELD(retype)
11946       && !IS_BITFIELD(resetype)) {
11947
11948         genDataPointerSet (right,result,ic);
11949         pic16_freeAsmop(result,NULL,ic,TRUE);
11950       return;
11951     }
11952
11953     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11954     pic16_aopOp(right,ic,FALSE);
11955     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11956
11957     /* if bitfield then unpack the bits */
11958     if (IS_BITFIELD(resetype)) {
11959       genPackBits (resetype, result, right, NULL, POINTER);
11960     } else {
11961       /* we have can just get the values */
11962       int size = AOP_SIZE(right);
11963       int offset = 0 ;    
11964
11965         pic16_loadFSR0(result, 0);
11966             
11967         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11968         while (size--) {
11969           if (AOP_TYPE(right) == AOP_LIT) {
11970             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11971             if (size) {
11972               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11973             } else {
11974               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11975             }
11976           } else { // no literal
11977             if(size) {
11978               pic16_emitpcode(POC_MOVFF,
11979                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11980                   pic16_popCopyReg(&pic16_pc_postinc0)));
11981             } else {
11982               pic16_emitpcode(POC_MOVFF,
11983                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11984                   pic16_popCopyReg(&pic16_pc_indf0)));
11985             }
11986           }
11987           
11988           offset++;
11989         }
11990     }
11991
11992     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11993     /* now some housekeeping stuff */
11994     if (aop) {
11995       /* we had to allocate for this iCode */
11996       pic16_freeAsmop(NULL,aop,ic,TRUE);
11997     } else { 
11998       /* we did not allocate which means left
11999        * already in a pointer register, then
12000        * if size > 0 && this could be used again
12001        * we have to point it back to where it 
12002        * belongs */
12003       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12004       if (AOP_SIZE(right) > 1
12005         && !OP_SYMBOL(result)->remat
12006         && ( OP_SYMBOL(result)->liveTo > ic->seq
12007         || ic->depth )) {
12008
12009           int size = AOP_SIZE(right) - 1;
12010
12011             while (size--)
12012               pic16_emitcode("decf","fsr0,f");
12013               //pic16_emitcode("dec","%s",rname);
12014       }
12015     }
12016
12017     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12018     /* done */
12019 //release:
12020     pic16_freeAsmop(right,NULL,ic,TRUE);
12021     pic16_freeAsmop(result,NULL,ic,TRUE);
12022 }
12023
12024 /*-----------------------------------------------------------------*/
12025 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12026 /*-----------------------------------------------------------------*/
12027 static void genPagedPointerSet (operand *right,
12028                                operand *result, 
12029                                iCode *ic)
12030 {
12031     asmop *aop = NULL;
12032     regs *preg = NULL ;
12033     char *rname , *l;
12034     sym_link *retype;
12035        
12036     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12037
12038     retype= getSpec(operandType(right));
12039     
12040     pic16_aopOp(result,ic,FALSE);
12041     
12042     /* if the value is already in a pointer register
12043        then don't need anything more */
12044     if (!AOP_INPREG(AOP(result))) {
12045         /* otherwise get a free pointer register */
12046         aop = newAsmop(0);
12047         preg = getFreePtr(ic,&aop,FALSE);
12048         pic16_emitcode("mov","%s,%s",
12049                 preg->name,
12050                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12051         rname = preg->name ;
12052     } else
12053         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12054     
12055     pic16_freeAsmop(result,NULL,ic,TRUE);
12056     pic16_aopOp (right,ic,FALSE);
12057
12058     /* if bitfield then unpack the bits */
12059     if (IS_BITFIELD(retype)) 
12060         genPackBits (retype,result,right,rname,PPOINTER);
12061     else {
12062         /* we have can just get the values */
12063         int size = AOP_SIZE(right);
12064         int offset = 0 ;        
12065         
12066         while (size--) {
12067             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12068             
12069             MOVA(l);
12070             pic16_emitcode("movx","@%s,a",rname);
12071
12072             if (size)
12073                 pic16_emitcode("inc","%s",rname);
12074
12075             offset++;
12076         }
12077     }
12078     
12079     /* now some housekeeping stuff */
12080     if (aop) {
12081         /* we had to allocate for this iCode */
12082         pic16_freeAsmop(NULL,aop,ic,TRUE);
12083     } else { 
12084         /* we did not allocate which means left
12085            already in a pointer register, then
12086            if size > 0 && this could be used again
12087            we have to point it back to where it 
12088            belongs */
12089         if (AOP_SIZE(right) > 1 &&
12090             !OP_SYMBOL(result)->remat &&
12091             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12092               ic->depth )) {
12093             int size = AOP_SIZE(right) - 1;
12094             while (size--)
12095                 pic16_emitcode("dec","%s",rname);
12096         }
12097     }
12098
12099     /* done */
12100     pic16_freeAsmop(right,NULL,ic,TRUE);
12101     
12102         
12103 }
12104
12105 #if 0
12106 /* This code is not adjusted to PIC16 and fails utterly...
12107  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12108
12109 /*-----------------------------------------------------------------*/
12110 /* genFarPointerSet - set value from far space                     */
12111 /*-----------------------------------------------------------------*/
12112 static void genFarPointerSet (operand *right,
12113                               operand *result, iCode *ic)
12114 {
12115     int size, offset ;
12116     sym_link *retype = getSpec(operandType(right));
12117
12118     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12119     pic16_aopOp(result,ic,FALSE);
12120
12121     /* if the operand is already in dptr 
12122     then we do nothing else we move the value to dptr */
12123     if (AOP_TYPE(result) != AOP_STR) {
12124         /* if this is remateriazable */
12125         if (AOP_TYPE(result) == AOP_IMMD)
12126             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12127         else { /* we need to get it byte by byte */
12128             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12129             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12130             if (options.model == MODEL_FLAT24)
12131             {
12132                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12133             }
12134         }
12135     }
12136     /* so dptr know contains the address */
12137     pic16_freeAsmop(result,NULL,ic,TRUE);
12138     pic16_aopOp(right,ic,FALSE);
12139
12140     /* if bit then unpack */
12141     if (IS_BITFIELD(retype)) 
12142         genPackBits(retype,result,right,"dptr",FPOINTER);
12143     else {
12144         size = AOP_SIZE(right);
12145         offset = 0 ;
12146
12147         while (size--) {
12148             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12149             MOVA(l);
12150             pic16_emitcode("movx","@dptr,a");
12151             if (size)
12152                 pic16_emitcode("inc","dptr");
12153         }
12154     }
12155
12156     pic16_freeAsmop(right,NULL,ic,TRUE);
12157 }
12158 #endif
12159
12160 /*-----------------------------------------------------------------*/
12161 /* genGenPointerSet - set value from generic pointer space         */
12162 /*-----------------------------------------------------------------*/
12163 #if 0
12164 static void genGenPointerSet (operand *right,
12165                               operand *result, iCode *ic)
12166 {
12167         int i, size, offset, lit;
12168         sym_link *retype = getSpec(operandType(right));
12169
12170         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12171
12172         pic16_aopOp(result,ic,FALSE);
12173         pic16_aopOp(right,ic,FALSE);
12174         size = AOP_SIZE(right);
12175         offset = 0;
12176
12177         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12178
12179         /* if the operand is already in dptr 
12180                 then we do nothing else we move the value to dptr */
12181         if (AOP_TYPE(result) != AOP_STR) {
12182                 /* if this is remateriazable */
12183                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12184                 // WARNING: anythig until "else" is untested!
12185                 if (AOP_TYPE(result) == AOP_IMMD) {
12186                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12187                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12188                         // load FSR0 from immediate
12189                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12190                         offset = 0;
12191                         while(size--) {
12192                                 if(size) {
12193                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12194                                 } else {
12195                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12196                                 }
12197                                 offset++;
12198                         }
12199                         goto release;
12200                 }
12201                 else { /* we need to get it byte by byte */
12202                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12203                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12204
12205                         // set up FSR0 with address of result
12206                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12207                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12208
12209                         /* hack hack! see if this the FSR. If so don't load W */
12210                         if(AOP_TYPE(right) != AOP_ACC) {
12211
12212                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12213
12214                                 if(AOP_TYPE(right) == AOP_LIT)
12215                                 {
12216                                         // copy literal
12217                                         // note: pic16_popGet handles sign extension
12218                                         for(i=0;i<size;i++) {
12219                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12220                                                 if(i < size-1)
12221                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12222                                                 else
12223                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12224                                         }
12225                                 } else {
12226                                         // copy regs
12227
12228                                         for(i=0;i<size;i++) {
12229                                                 if(i < size-1)
12230                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12231                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12232                                                 else
12233                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12234                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12235                                         }
12236                                 }
12237                                 goto release;
12238                         } 
12239                         // right = ACC
12240                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12241                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12242                         goto release;
12243         } // if (AOP_TYPE(result) != AOP_IMMD)
12244
12245         } // if (AOP_TYPE(result) != AOP_STR)
12246         /* so dptr know contains the address */
12247
12248
12249         /* if bit then unpack */
12250         if (IS_BITFIELD(retype)) 
12251                 genPackBits(retype,result,right,"dptr",GPOINTER);
12252         else {
12253                 size = AOP_SIZE(right);
12254                 offset = 0 ;
12255
12256                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12257
12258                 // set up FSR0 with address of result
12259                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12260                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12261         
12262                 while (size--) {
12263                         if (AOP_TYPE(right) == AOP_LIT) {
12264                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12265                                 if (size) {
12266                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12267                                 } else {
12268                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12269                                 }
12270                         } else { // no literal
12271                                 if(size) {
12272                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12273                                 } else {
12274                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12275                                 }
12276                         }
12277                         offset++;
12278                 }
12279         }
12280
12281         release:
12282         pic16_freeAsmop(right,NULL,ic,TRUE);
12283         pic16_freeAsmop(result,NULL,ic,TRUE);
12284 }
12285 #endif
12286
12287 static void genGenPointerSet (operand *right,
12288                               operand *result, iCode *ic)
12289 {
12290   int size;
12291   sym_link *retype = getSpec(operandType(result));
12292
12293     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12294
12295     pic16_aopOp(result,ic,FALSE);
12296     pic16_aopOp(right,ic,FALSE);
12297     size = AOP_SIZE(right);
12298
12299     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12300
12301
12302     /* if bit then unpack */
12303     if (IS_BITFIELD(retype)) {
12304 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12305       genPackBits(retype,result,right,"dptr",GPOINTER);
12306       goto release;
12307     }
12308
12309     size = AOP_SIZE(right);
12310
12311     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12312
12313
12314     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12315
12316     /* value of right+0 is placed on stack, which will be retrieved
12317      * by the support function thus restoring the stack. The important
12318      * thing is that there is no need to manually restore stack pointer
12319      * here */
12320     pushaop(AOP(right), 0);
12321 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12322     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12323     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12324     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12325     
12326     /* load address to write to in WREG:FSR0H:FSR0L */
12327     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12328                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12329     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12330                                 pic16_popCopyReg(&pic16_pc_prodl)));
12331     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12332     
12333     pic16_callGenericPointerRW(1, size);
12334
12335 release:
12336     pic16_freeAsmop(right,NULL,ic,TRUE);
12337     pic16_freeAsmop(result,NULL,ic,TRUE);
12338 }
12339
12340 /*-----------------------------------------------------------------*/
12341 /* genPointerSet - stores the value into a pointer location        */
12342 /*-----------------------------------------------------------------*/
12343 static void genPointerSet (iCode *ic)
12344 {    
12345   operand *right, *result ;
12346   sym_link *type, *etype;
12347   int p_type;
12348
12349     FENTRY;
12350
12351     right = IC_RIGHT(ic);
12352     result = IC_RESULT(ic) ;
12353
12354     /* depending on the type of pointer we need to
12355     move it to the correct pointer register */
12356     type = operandType(result);
12357     etype = getSpec(type);
12358     
12359     /* if left is of type of pointer then it is simple */
12360     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12361         p_type = DCL_TYPE(type);
12362     }
12363     else {
12364         /* we have to go by the storage class */
12365         p_type = PTR_TYPE(SPEC_OCLS(etype));
12366
12367 /*      if (SPEC_OCLS(etype)->codesp ) { */
12368 /*          p_type = CPOINTER ;  */
12369 /*      } */
12370 /*      else */
12371 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12372 /*              p_type = FPOINTER ; */
12373 /*          else */
12374 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12375 /*                  p_type = PPOINTER ; */
12376 /*              else */
12377 /*                  if (SPEC_OCLS(etype) == idata ) */
12378 /*                      p_type = IPOINTER ; */
12379 /*                  else */
12380 /*                      p_type = POINTER ; */
12381     }
12382
12383     /* now that we have the pointer type we assign
12384     the pointer values */
12385     switch (p_type) {
12386       case POINTER:
12387       case FPOINTER:
12388       case IPOINTER:
12389         genNearPointerSet (right,result,ic);
12390         break;
12391
12392       case PPOINTER:
12393         genPagedPointerSet (right,result,ic);
12394         break;
12395
12396 #if 0
12397       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12398       case FPOINTER:
12399         genFarPointerSet (right,result,ic);
12400         break;
12401 #endif
12402         
12403       case GPOINTER:
12404         genGenPointerSet (right,result,ic);
12405         break;
12406
12407       default:
12408         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12409           "genPointerSet: illegal pointer type");
12410     }
12411 }
12412
12413 /*-----------------------------------------------------------------*/
12414 /* genIfx - generate code for Ifx statement                        */
12415 /*-----------------------------------------------------------------*/
12416 static void genIfx (iCode *ic, iCode *popIc)
12417 {
12418   operand *cond = IC_COND(ic);
12419   int isbit =0;
12420
12421     FENTRY;
12422
12423     pic16_aopOp(cond,ic,FALSE);
12424
12425     /* get the value into acc */
12426     if (AOP_TYPE(cond) != AOP_CRY)
12427       pic16_toBoolean(cond);
12428     else
12429       isbit = 1;
12430     /* the result is now in the accumulator */
12431     pic16_freeAsmop(cond,NULL,ic,TRUE);
12432
12433     /* if there was something to be popped then do it */
12434     if (popIc)
12435       genIpop(popIc);
12436
12437     /* if the condition is  a bit variable */
12438     if (isbit && IS_ITEMP(cond) && 
12439         SPIL_LOC(cond)) {
12440       genIfxJump(ic,"c");
12441       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12442     } else {
12443       if (isbit && !IS_ITEMP(cond))
12444         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12445         else
12446         genIfxJump(ic,"a");
12447     }
12448     ic->generated = 1;
12449 }
12450
12451 /*-----------------------------------------------------------------*/
12452 /* genAddrOf - generates code for address of                       */
12453 /*-----------------------------------------------------------------*/
12454 static void genAddrOf (iCode *ic)
12455 {
12456   operand *result, *left;
12457   int size;
12458   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12459   pCodeOp *pcop0, *pcop1, *pcop2;
12460
12461     FENTRY;
12462
12463     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12464
12465     sym = OP_SYMBOL( IC_LEFT(ic) );
12466     
12467     if(sym->onStack) {
12468       /* get address of symbol on stack */
12469       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12470 #if 0
12471       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12472                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12473 #endif
12474
12475       // operands on stack are accessible via "FSR2 + index" with index
12476       // starting at 2 for arguments and growing from 0 downwards for
12477       // local variables (index == 0 is not assigned so we add one here)
12478       {
12479         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12480
12481           if (soffs <= 0) {
12482             assert (soffs < 0);
12483             soffs++;
12484           } // if
12485
12486           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12487           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12488           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12489           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12490           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12491           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12492           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12493       }
12494
12495       goto release;
12496     }
12497         
12498 //      if(pic16_debug_verbose) {
12499 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12500 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12501 //      }
12502         
12503     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12504     size = AOP_SIZE(IC_RESULT(ic));
12505
12506     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12507     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12508     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12509         
12510     if (size == 3) {
12511       pic16_emitpcode(POC_MOVLW, pcop0);
12512       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12513       pic16_emitpcode(POC_MOVLW, pcop1);
12514       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12515       pic16_emitpcode(POC_MOVLW, pcop2);
12516       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12517     } else
12518     if (size == 2) {
12519       pic16_emitpcode(POC_MOVLW, pcop0);
12520       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12521       pic16_emitpcode(POC_MOVLW, pcop1);
12522     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12523     } else {
12524       pic16_emitpcode(POC_MOVLW, pcop0);
12525       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12526     }
12527
12528     pic16_freeAsmop(left, NULL, ic, FALSE);
12529 release:
12530     pic16_freeAsmop(result,NULL,ic,TRUE);
12531 }
12532
12533
12534 #if 0
12535 /*-----------------------------------------------------------------*/
12536 /* genFarFarAssign - assignment when both are in far space         */
12537 /*-----------------------------------------------------------------*/
12538 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12539 {
12540     int size = AOP_SIZE(right);
12541     int offset = 0;
12542     char *l ;
12543     /* first push the right side on to the stack */
12544     while (size--) {
12545         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12546         MOVA(l);
12547         pic16_emitcode ("push","acc");
12548     }
12549     
12550     pic16_freeAsmop(right,NULL,ic,FALSE);
12551     /* now assign DPTR to result */
12552     pic16_aopOp(result,ic,FALSE);
12553     size = AOP_SIZE(result);
12554     while (size--) {
12555         pic16_emitcode ("pop","acc");
12556         pic16_aopPut(AOP(result),"a",--offset);
12557     }
12558     pic16_freeAsmop(result,NULL,ic,FALSE);
12559         
12560 }
12561 #endif
12562
12563 /*-----------------------------------------------------------------*/
12564 /* genAssign - generate code for assignment                        */
12565 /*-----------------------------------------------------------------*/
12566 static void genAssign (iCode *ic)
12567 {
12568   operand *result, *right;
12569   sym_link *restype, *rtype;
12570   int size, offset,know_W;
12571   unsigned long lit = 0L;
12572
12573     result = IC_RESULT(ic);
12574     right  = IC_RIGHT(ic) ;
12575
12576     FENTRY;
12577   
12578     /* if they are the same */
12579     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12580       return ;
12581
12582     /* reversed order operands are aopOp'ed so that result operand
12583      * is effective in case right is a stack symbol. This maneauver
12584      * allows to use the _G.resDirect flag later */
12585      pic16_aopOp(result,ic,TRUE);
12586     pic16_aopOp(right,ic,FALSE);
12587
12588     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12589
12590     /* if they are the same registers */
12591     if (pic16_sameRegs(AOP(right),AOP(result)))
12592       goto release;
12593
12594     /* if the result is a bit */
12595     if (AOP_TYPE(result) == AOP_CRY) {
12596       /* if the right size is a literal then
12597          we know what the value is */
12598       if (AOP_TYPE(right) == AOP_LIT) {
12599           
12600         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12601             pic16_popGet(AOP(result),0));
12602
12603         if (((int) operandLitValue(right))) 
12604           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12605               AOP(result)->aopu.aop_dir,
12606               AOP(result)->aopu.aop_dir);
12607         else
12608           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12609               AOP(result)->aopu.aop_dir,
12610               AOP(result)->aopu.aop_dir);
12611         
12612         goto release;
12613       }
12614
12615       /* the right is also a bit variable */
12616       if (AOP_TYPE(right) == AOP_CRY) {
12617         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12618         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12619         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12620
12621         goto release ;
12622       }
12623
12624       /* we need to or */
12625       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12626       pic16_toBoolean(right);
12627       emitSKPZ;
12628       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12629       //pic16_aopPut(AOP(result),"a",0);
12630       goto release ;
12631     }
12632
12633     /* bit variables done */
12634     /* general case */
12635     size = AOP_SIZE(result);
12636     offset = 0 ;
12637
12638   /* bit variables done */
12639   /* general case */
12640   size = AOP_SIZE(result);
12641   restype = operandType(result);
12642   rtype = operandType(right);
12643   offset = 0 ;
12644
12645   if(AOP_TYPE(right) == AOP_LIT) {
12646     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12647     {
12648       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12649
12650       /* patch tag for literals that are cast to pointers */
12651       if (IS_CODEPTR(restype)) {
12652         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12653         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12654       } else {
12655         if (IS_GENPTR(restype))
12656         {
12657           if (IS_CODEPTR(rtype)) {
12658             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12659             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12660           } else if (PIC_IS_DATA_PTR(rtype)) {
12661             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12662             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12663           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12664             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12665           } else if (IS_PTR(rtype)) {
12666             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12667             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12668           }
12669         }
12670       }
12671     } else {
12672       union {
12673         unsigned long lit_int;
12674         float lit_float;
12675       } info;
12676
12677
12678       if(IS_FIXED16X16(operandType(right))) {
12679         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12680       } else {
12681         /* take care if literal is a float */
12682         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12683         lit = info.lit_int;
12684       }
12685     }
12686   }
12687
12688 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12689 //                      sizeof(unsigned long int), sizeof(float));
12690
12691
12692     if (AOP_TYPE(right) == AOP_REG) {
12693       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12694       while (size--) {
12695         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12696       } // while
12697       goto release;
12698     }
12699
12700     /* when do we have to read the program memory?
12701      * - if right itself is a symbol in code space
12702      *   (we don't care what it points to if it's a pointer)
12703      * - AND right is not a function (we would want its address)
12704      */
12705     if(AOP_TYPE(right) != AOP_LIT
12706       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12707       && !IS_FUNC(OP_SYM_TYPE(right))
12708       && !IS_ITEMP(right)) {
12709
12710       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12711       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12712       
12713       // set up table pointer
12714       if(is_LitOp(right)) {
12715 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12716         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12717         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12718         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12719         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12720         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12721         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12722       } else {
12723 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12724         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12725             pic16_popCopyReg(&pic16_pc_tblptrl)));
12726         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12727             pic16_popCopyReg(&pic16_pc_tblptrh)));
12728         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12729             pic16_popCopyReg(&pic16_pc_tblptru)));
12730       }
12731
12732       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12733       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12734       while(size--) {
12735         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12736         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12737             pic16_popGet(AOP(result),offset)));
12738         offset++;
12739       }
12740
12741       /* FIXME: for pointers we need to extend differently (according
12742        * to pointer type DATA/CODE/EEPROM/... :*/
12743       size = getSize(OP_SYM_TYPE(right));
12744       if(AOP_SIZE(result) > size) {
12745         size = AOP_SIZE(result) - size;
12746         while(size--) {
12747           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12748           offset++;
12749         }
12750       }
12751       goto release;
12752     }
12753
12754 #if 0
12755     /* VR - What is this?! */
12756     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12757       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12758       
12759       if(aopIdx(AOP(result),0) == 4) {
12760         /* this is a workaround to save value of right into wreg too,
12761          * value of wreg is going to be used later */
12762         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12763         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12764         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12765         goto release;
12766       } else
12767 //      assert(0);
12768       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12769     }
12770 #endif
12771
12772     size = AOP_SIZE(right);
12773     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12774     know_W=-1;
12775     while (size--) {
12776       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12777       if(AOP_TYPE(right) == AOP_LIT) {
12778         if(lit&0xff) {
12779           if(know_W != (lit&0xff))
12780             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12781           know_W = lit&0xff;
12782           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12783         } else
12784           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12785
12786         lit >>= 8;
12787
12788       } else if (AOP_TYPE(right) == AOP_CRY) {
12789         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12790         if(offset == 0) {
12791           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12792           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12793           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12794         }
12795       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12796         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12797         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12798       } else {
12799         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12800
12801         if(!_G.resDirect) {                                             /* use this aopForSym feature */
12802           if(AOP_TYPE(result) == AOP_ACC) {
12803             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12804           } else
12805             if(AOP_TYPE(right) == AOP_ACC) {
12806               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12807             } else {
12808               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12809             }
12810         }
12811       }
12812
12813       offset++;
12814     }
12815     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12816   
12817 release:
12818   pic16_freeAsmop (right,NULL,ic,FALSE);
12819   pic16_freeAsmop (result,NULL,ic,TRUE);
12820
12821
12822 /*-----------------------------------------------------------------*/
12823 /* genJumpTab - generates code for jump table                       */
12824 /*-----------------------------------------------------------------*/
12825 static void genJumpTab (iCode *ic)
12826 {
12827   symbol *jtab;
12828   char *l;
12829   pCodeOp *jt_offs;
12830   pCodeOp *jt_offs_hi;
12831   pCodeOp *jt_label;
12832
12833     FENTRY;
12834
12835     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12836     /* get the condition into accumulator */
12837     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12838     MOVA(l);
12839     /* multiply by three */
12840     pic16_emitcode("add","a,acc");
12841     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12842
12843     jtab = newiTempLabel(NULL);
12844     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12845     pic16_emitcode("jmp","@a+dptr");
12846     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12847
12848 #if 0
12849     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12850     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12851     emitSKPNC;
12852     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12853     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12854     pic16_emitpLabel(jtab->key);
12855
12856 #else
12857
12858     jt_offs = pic16_popGetTempReg(0);
12859     jt_offs_hi = pic16_popGetTempReg(1);
12860     jt_label = pic16_popGetLabel (jtab->key);
12861     //fprintf (stderr, "Creating jump table...\n");
12862
12863     // calculate offset into jump table (idx * sizeof (GOTO))
12864     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12865     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12866     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12867     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12868     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12869     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12870     pic16_emitpcode(POC_MOVWF , jt_offs);
12871
12872     // prepare PCLATx (set to first entry in jump table)
12873     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12874     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12875     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12876     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12877     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12878
12879     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12880     pic16_emitpcode(POC_ADDWF , jt_offs);
12881     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12882     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12883     emitSKPNC;
12884     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12885
12886     // release temporaries and prepare jump into table (new PCL --> WREG)
12887     pic16_emitpcode(POC_MOVFW , jt_offs);
12888     pic16_popReleaseTempReg (jt_offs_hi, 1);
12889     pic16_popReleaseTempReg (jt_offs, 0);
12890
12891     // jump into the table
12892     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12893
12894     pic16_emitpLabelFORCE(jtab->key);
12895 #endif
12896
12897     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12898 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12899
12900     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12901     /* now generate the jump labels */
12902     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12903          jtab = setNextItem(IC_JTLABELS(ic))) {
12904 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12905         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12906         
12907     }
12908     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12909
12910 }
12911
12912 /*-----------------------------------------------------------------*/
12913 /* genMixedOperation - gen code for operators between mixed types  */
12914 /*-----------------------------------------------------------------*/
12915 /*
12916   TSD - Written for the PIC port - but this unfortunately is buggy.
12917   This routine is good in that it is able to efficiently promote 
12918   types to different (larger) sizes. Unfortunately, the temporary
12919   variables that are optimized out by this routine are sometimes
12920   used in other places. So until I know how to really parse the 
12921   iCode tree, I'm going to not be using this routine :(.
12922 */
12923 static int genMixedOperation (iCode *ic)
12924 {
12925 #if 0
12926   operand *result = IC_RESULT(ic);
12927   sym_link *ctype = operandType(IC_LEFT(ic));
12928   operand *right = IC_RIGHT(ic);
12929   int ret = 0;
12930   int big,small;
12931   int offset;
12932
12933   iCode *nextic;
12934   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12935
12936   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12937
12938   nextic = ic->next;
12939   if(!nextic)
12940     return 0;
12941
12942   nextright = IC_RIGHT(nextic);
12943   nextleft  = IC_LEFT(nextic);
12944   nextresult = IC_RESULT(nextic);
12945
12946   pic16_aopOp(right,ic,FALSE);
12947   pic16_aopOp(result,ic,FALSE);
12948   pic16_aopOp(nextright,  nextic, FALSE);
12949   pic16_aopOp(nextleft,   nextic, FALSE);
12950   pic16_aopOp(nextresult, nextic, FALSE);
12951
12952   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12953
12954     operand *t = right;
12955     right = nextright;
12956     nextright = t; 
12957
12958     pic16_emitcode(";remove right +","");
12959
12960   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12961 /*
12962     operand *t = right;
12963     right = nextleft;
12964     nextleft = t; 
12965 */
12966     pic16_emitcode(";remove left +","");
12967   } else
12968     return 0;
12969
12970   big = AOP_SIZE(nextleft);
12971   small = AOP_SIZE(nextright);
12972
12973   switch(nextic->op) {
12974
12975   case '+':
12976     pic16_emitcode(";optimize a +","");
12977     /* if unsigned or not an integral type */
12978     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12979       pic16_emitcode(";add a bit to something","");
12980     } else {
12981
12982       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12983
12984       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12985         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12986         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12987       } else
12988         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12989
12990       offset = 0;
12991       while(--big) {
12992
12993         offset++;
12994
12995         if(--small) {
12996           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12997             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12998             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12999           }
13000
13001           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13002           emitSKPNC;
13003           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13004                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13005                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13006           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13007           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13008
13009         } else {
13010           pic16_emitcode("rlf","known_zero,w");
13011
13012           /*
13013             if right is signed
13014               btfsc  right,7
13015                addlw ff
13016           */
13017           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13018             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13019             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13020           } else {
13021             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13022           }
13023         }
13024       }
13025       ret = 1;
13026     }
13027   }
13028   ret = 1;
13029
13030 release:
13031   pic16_freeAsmop(right,NULL,ic,TRUE);
13032   pic16_freeAsmop(result,NULL,ic,TRUE);
13033   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13034   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13035   if(ret)
13036     nextic->generated = 1;
13037
13038   return ret;
13039 #else
13040   return 0;
13041 #endif
13042 }
13043 /*-----------------------------------------------------------------*/
13044 /* genCast - gen code for casting                                  */
13045 /*-----------------------------------------------------------------*/
13046 static void genCast (iCode *ic)
13047 {
13048   operand *result = IC_RESULT(ic);
13049   sym_link *ctype = operandType(IC_LEFT(ic));
13050   sym_link *rtype = operandType(IC_RIGHT(ic));
13051   sym_link *restype = operandType(IC_RESULT(ic));
13052   operand *right = IC_RIGHT(ic);
13053   int size, offset ;
13054
13055
13056     FENTRY;
13057
13058         /* if they are equivalent then do nothing */
13059 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13060 //              return ;
13061
13062         pic16_aopOp(result,ic,FALSE);
13063         pic16_aopOp(right,ic,FALSE) ;
13064
13065         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13066
13067
13068         /* if the result is a bit */
13069         if (AOP_TYPE(result) == AOP_CRY) {
13070         
13071                 /* if the right size is a literal then
13072                  * we know what the value is */
13073                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13074
13075                 if (AOP_TYPE(right) == AOP_LIT) {
13076                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13077                                 pic16_popGet(AOP(result),0));
13078
13079                         if (((int) operandLitValue(right))) 
13080                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13081                                         AOP(result)->aopu.aop_dir,
13082                                         AOP(result)->aopu.aop_dir);
13083                         else
13084                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13085                                         AOP(result)->aopu.aop_dir,
13086                                         AOP(result)->aopu.aop_dir);
13087                         goto release;
13088                 }
13089
13090                 /* the right is also a bit variable */
13091                 if (AOP_TYPE(right) == AOP_CRY) {
13092                         emitCLRC;
13093                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13094
13095                         pic16_emitcode("clrc","");
13096                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13097                                 AOP(right)->aopu.aop_dir,
13098                                 AOP(right)->aopu.aop_dir);
13099                         pic16_aopPut(AOP(result),"c",0);
13100                         goto release ;
13101                 }
13102
13103                 /* we need to or */
13104                 if (AOP_TYPE(right) == AOP_REG) {
13105                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13106                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13107                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13108                 }
13109                 pic16_toBoolean(right);
13110                 pic16_aopPut(AOP(result),"a",0);
13111                 goto release ;
13112         }
13113
13114         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13115           int offset = 1;
13116
13117                 size = AOP_SIZE(result);
13118
13119                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13120
13121                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13122                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13123                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13124
13125                 while (size--)
13126                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13127
13128                 goto release;
13129         }
13130
13131         if(IS_BITFIELD(getSpec(restype))
13132           && IS_BITFIELD(getSpec(rtype))) {
13133           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13134         }
13135         
13136         /* port from pic14 to cope with generic pointers */
13137         if (PIC_IS_TAGGED(restype))
13138         {
13139           operand *result = IC_RESULT(ic);
13140           //operand *left = IC_LEFT(ic);
13141           operand *right = IC_RIGHT(ic);
13142           int tag = 0xff;
13143
13144           /* copy common part */
13145           int max, size = AOP_SIZE(result);
13146           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13147           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13148
13149           max = size;
13150           while (size--)
13151           {
13152             pic16_mov2w (AOP(right), size);
13153             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13154           } // while
13155
13156           /* upcast into generic pointer type? */
13157           if (IS_GENPTR(restype)
13158               && !PIC_IS_TAGGED(rtype)
13159               && (AOP_SIZE(result) > max))
13160           {
13161             /* determine appropriate tag for right */
13162             if (PIC_IS_DATA_PTR(rtype))
13163               tag = GPTR_TAG_DATA;
13164             else if (IS_CODEPTR(rtype))
13165               tag = GPTR_TAG_CODE;
13166             else if (PIC_IS_DATA_PTR(ctype)) {
13167               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13168               tag = GPTR_TAG_DATA;
13169             } else if (IS_CODEPTR(ctype)) {
13170               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13171               tag = GPTR_TAG_CODE;
13172             } else if (IS_PTR(rtype)) {
13173               PERFORM_ONCE(weirdcast,
13174               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13175               );
13176               tag = GPTR_TAG_DATA;
13177             } else {
13178               PERFORM_ONCE(weirdcast,
13179               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13180               );
13181               tag = GPTR_TAG_DATA;
13182             }
13183
13184             assert (AOP_SIZE(result) == 3);
13185             /* zero-extend address... */
13186             for (size = max; size < AOP_SIZE(result)-1; size++)
13187               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13188             /* ...and add tag */
13189             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13190           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13191             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13192             for (size = max; size < AOP_SIZE(result)-1; size++)
13193               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13194             /* add __code tag */
13195             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13196           } else if (AOP_SIZE(result) > max) {
13197             /* extend non-pointers */
13198             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13199             pic16_addSign(result, max, 0);
13200           } // if
13201           goto release;
13202         }
13203
13204         /* if they are the same size : or less */
13205         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13206
13207                 /* if they are in the same place */
13208                 if (pic16_sameRegs(AOP(right),AOP(result)))
13209                         goto release;
13210
13211                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13212 #if 0
13213                 if (IS_PTR_CONST(rtype))
13214 #else
13215                 if (IS_CODEPTR(rtype))
13216 #endif
13217                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13218
13219 #if 0
13220                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13221 #else
13222                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13223 #endif
13224                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13225
13226 #if 0
13227                 if(AOP_TYPE(right) == AOP_IMMD) {
13228                   pCodeOp *pcop0, *pcop1, *pcop2;
13229                   symbol *sym = OP_SYMBOL( right );
13230
13231                         size = AOP_SIZE(result);
13232                         /* low */
13233                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13234                         /* high */
13235                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13236                         /* upper */
13237                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13238         
13239                         if (size == 3) {
13240                                 pic16_emitpcode(POC_MOVLW, pcop0);
13241                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13242                                 pic16_emitpcode(POC_MOVLW, pcop1);
13243                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13244                                 pic16_emitpcode(POC_MOVLW, pcop2);
13245                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13246                         } else
13247                         if (size == 2) {
13248                                 pic16_emitpcode(POC_MOVLW, pcop0);
13249                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13250                                 pic16_emitpcode(POC_MOVLW, pcop1);
13251                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13252                         } else {
13253                                 pic16_emitpcode(POC_MOVLW, pcop0);
13254                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13255                         }
13256                 } else
13257 #endif
13258                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13259                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13260                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13261
13262                         if(AOP_SIZE(result) < 2) {
13263                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13264                         } else {
13265                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13266                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13267                         }
13268                 } else {
13269                         /* if they in different places then copy */
13270                         size = AOP_SIZE(result);
13271                         offset = 0 ;
13272                         while (size--) {
13273                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13274                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13275                                 offset++;
13276                         }
13277                 }
13278                 goto release;
13279         }
13280
13281         /* if the result is of type pointer */
13282         if (IS_PTR(ctype)) {
13283           int p_type;
13284           sym_link *type = operandType(right);
13285           sym_link *etype = getSpec(type);
13286
13287                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13288
13289                 /* pointer to generic pointer */
13290                 if (IS_GENPTR(ctype)) {
13291                   char *l = zero;
13292             
13293                         if (IS_PTR(type)) 
13294                                 p_type = DCL_TYPE(type);
13295                         else {
13296                 /* we have to go by the storage class */
13297                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13298
13299 /*              if (SPEC_OCLS(etype)->codesp )  */
13300 /*                  p_type = CPOINTER ;  */
13301 /*              else */
13302 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13303 /*                      p_type = FPOINTER ; */
13304 /*                  else */
13305 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13306 /*                          p_type = PPOINTER; */
13307 /*                      else */
13308 /*                          if (SPEC_OCLS(etype) == idata ) */
13309 /*                              p_type = IPOINTER ; */
13310 /*                          else */
13311 /*                              p_type = POINTER ; */
13312             }
13313                 
13314             /* the first two bytes are known */
13315       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13316             size = GPTRSIZE - 1; 
13317             offset = 0 ;
13318             while (size--) {
13319               if(offset < AOP_SIZE(right)) {
13320                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13321                 pic16_mov2f(AOP(result), AOP(right), offset);
13322 /*
13323                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13324                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13325                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13326                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13327                 } else { 
13328                   
13329                   pic16_aopPut(AOP(result),
13330                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13331                          offset);
13332                 }
13333 */
13334               } else 
13335                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13336               offset++;
13337             }
13338             /* the last byte depending on type */
13339             switch (p_type) {
13340             case IPOINTER:
13341             case POINTER:
13342             case FPOINTER:
13343                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13344                 break;
13345
13346             case CPOINTER:
13347                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13348                 break;
13349
13350             case PPOINTER:
13351               pic16_emitcode(";BUG!? ","%d",__LINE__);
13352                 l = "#0x03";
13353                 break;
13354
13355             case GPOINTER:
13356                 if (GPTRSIZE > AOP_SIZE(right)) {
13357                   // assume __data pointer... THIS MIGHT BE WRONG!
13358                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13359                 } else {
13360                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13361                 }
13362               break;
13363               
13364             default:
13365                 /* this should never happen */
13366                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13367                        "got unknown pointer type");
13368                 exit(1);
13369             }
13370             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13371             goto release ;
13372         }
13373         
13374         
13375         assert( 0 );
13376         /* just copy the pointers */
13377         size = AOP_SIZE(result);
13378         offset = 0 ;
13379         while (size--) {
13380             pic16_aopPut(AOP(result),
13381                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13382                    offset);
13383             offset++;
13384         }
13385         goto release ;
13386     }
13387     
13388
13389
13390     /* so we now know that the size of destination is greater
13391     than the size of the source.
13392     Now, if the next iCode is an operator then we might be
13393     able to optimize the operation without performing a cast.
13394     */
13395     if(genMixedOperation(ic))
13396       goto release;
13397
13398     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13399     
13400     /* we move to result for the size of source */
13401     size = AOP_SIZE(right);
13402     offset = 0 ;
13403
13404     while (size--) {
13405       if(!_G.resDirect)
13406         pic16_mov2f(AOP(result), AOP(right), offset);
13407       offset++;
13408     }
13409
13410     /* now depending on the sign of the destination */
13411     size = AOP_SIZE(result) - AOP_SIZE(right);
13412     /* if unsigned or not an integral type */
13413     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13414       while (size--)
13415         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13416     } else {
13417       /* we need to extend the sign :( */
13418
13419       if(size == 1) {
13420         /* Save one instruction of casting char to int */
13421         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13422         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13423         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13424       } else {
13425         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13426
13427         if(offset)
13428           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13429         else
13430           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13431         
13432         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13433
13434         while (size--)
13435           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13436       }
13437     }
13438
13439 release:
13440     pic16_freeAsmop(right,NULL,ic,TRUE);
13441     pic16_freeAsmop(result,NULL,ic,TRUE);
13442
13443 }
13444
13445 /*-----------------------------------------------------------------*/
13446 /* genDjnz - generate decrement & jump if not zero instrucion      */
13447 /*-----------------------------------------------------------------*/
13448 static int genDjnz (iCode *ic, iCode *ifx)
13449 {
13450     symbol *lbl, *lbl1;
13451     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13452
13453     if (!ifx)
13454         return 0;
13455     
13456     /* if the if condition has a false label
13457        then we cannot save */
13458     if (IC_FALSE(ifx))
13459         return 0;
13460
13461     /* if the minus is not of the form 
13462        a = a - 1 */
13463     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13464         !IS_OP_LITERAL(IC_RIGHT(ic)))
13465         return 0;
13466
13467     if (operandLitValue(IC_RIGHT(ic)) != 1)
13468         return 0;
13469
13470     /* if the size of this greater than one then no
13471        saving */
13472     if (getSize(operandType(IC_RESULT(ic))) > 1)
13473         return 0;
13474
13475     /* otherwise we can save BIG */
13476     lbl = newiTempLabel(NULL);
13477     lbl1= newiTempLabel(NULL);
13478
13479     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13480     
13481     if (IS_AOP_PREG(IC_RESULT(ic))) {
13482         pic16_emitcode("dec","%s",
13483                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13484         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13485         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13486     } else {    
13487
13488
13489       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13490       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13491
13492       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13493       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13494
13495     }
13496     
13497     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13498     ifx->generated = 1;
13499     return 1;
13500 }
13501
13502 /*-----------------------------------------------------------------*/
13503 /* genReceive - generate code for a receive iCode                  */
13504 /*-----------------------------------------------------------------*/
13505 static void genReceive (iCode *ic)
13506 {    
13507
13508   FENTRY;
13509
13510 #if 0
13511   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13512         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13513 #endif
13514 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13515
13516   if (isOperandInFarSpace(IC_RESULT(ic))
13517       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13518           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13519
13520     int size = getSize(operandType(IC_RESULT(ic)));
13521     int offset =  pic16_fReturnSizePic - size;
13522
13523       assert( 0 );
13524       while (size--) {
13525         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13526                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13527                       offset++;
13528         }
13529
13530       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13531
13532       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13533       size = AOP_SIZE(IC_RESULT(ic));
13534       offset = 0;
13535       while (size--) {
13536         pic16_emitcode ("pop","acc");
13537         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13538       }
13539   } else {
13540     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13541     _G.accInUse++;
13542     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13543     _G.accInUse--;
13544
13545     /* set pseudo stack pointer to where it should be - dw*/
13546     GpsuedoStkPtr = ic->parmBytes;
13547
13548     /* setting GpsuedoStkPtr has side effects here: */
13549     /* FIXME: What's the correct size of the return(ed) value?
13550      *        For now, assuming '4' as before... */
13551     assignResultValue(IC_RESULT(ic), 4, 0);
13552   }
13553
13554   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13555 }
13556
13557 /*-----------------------------------------------------------------*/
13558 /* genDummyRead - generate code for dummy read of volatiles        */
13559 /*-----------------------------------------------------------------*/
13560 static void
13561 genDummyRead (iCode * ic)
13562 {
13563   operand *op;
13564   int i;
13565
13566   op = IC_RIGHT(ic);
13567   if (op && IS_SYMOP(op)) {
13568     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13569       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13570       return;
13571     }
13572     pic16_aopOp (op, ic, FALSE);
13573     for (i=0; i < AOP_SIZE(op); i++) {
13574       // may need to protect this from the peepholer -- this is not nice but works...
13575       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13576       pic16_mov2w (AOP(op),i);
13577       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13578     } // for i
13579     pic16_freeAsmop (op, NULL, ic, TRUE);
13580   } else if (op) {
13581     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13582   } // if
13583 }
13584
13585 /*-----------------------------------------------------------------*/
13586 /* genpic16Code - generate code for pic16 based controllers        */
13587 /*-----------------------------------------------------------------*/
13588 /*
13589  * At this point, ralloc.c has gone through the iCode and attempted
13590  * to optimize in a way suitable for a PIC. Now we've got to generate
13591  * PIC instructions that correspond to the iCode.
13592  *
13593  * Once the instructions are generated, we'll pass through both the
13594  * peep hole optimizer and the pCode optimizer.
13595  *-----------------------------------------------------------------*/
13596
13597 void genpic16Code (iCode *lic)
13598 {
13599   iCode *ic;
13600   int cln = 0;
13601
13602     lineHead = lineCurr = NULL;
13603
13604     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13605     pic16_addpBlock(pb);
13606
13607 #if 0
13608     /* if debug information required */
13609     if (options.debug && currFunc) {
13610       if (currFunc) {
13611         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13612       }
13613     }
13614 #endif
13615
13616     for (ic = lic ; ic ; ic = ic->next ) {
13617
13618       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13619       if ( cln != ic->lineno ) {
13620         if ( options.debug ) {
13621           debugFile->writeCLine (ic);
13622         }
13623         
13624         if(!options.noCcodeInAsm) {
13625           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13626               printCLine(ic->filename, ic->lineno)));
13627         }
13628
13629         cln = ic->lineno ;
13630       }
13631         
13632       if(options.iCodeInAsm) {
13633         char *l;
13634
13635           /* insert here code to print iCode as comment */
13636           l = Safe_strdup(printILine(ic));
13637           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13638       }
13639
13640       /* if the result is marked as
13641        * spilt and rematerializable or code for
13642        * this has already been generated then
13643        * do nothing */
13644       if (resultRemat(ic) || ic->generated ) 
13645         continue ;
13646         
13647       /* depending on the operation */
13648       switch (ic->op) {
13649         case '!' :
13650           pic16_genNot(ic);
13651           break;
13652             
13653         case '~' :
13654           pic16_genCpl(ic);
13655           break;
13656             
13657         case UNARYMINUS:
13658           genUminus (ic);
13659           break;
13660             
13661         case IPUSH:
13662           genIpush (ic);
13663           break;
13664             
13665         case IPOP:
13666           /* IPOP happens only when trying to restore a 
13667            * spilt live range, if there is an ifx statement
13668            * following this pop then the if statement might
13669            * be using some of the registers being popped which
13670            * would destroy the contents of the register so
13671            * we need to check for this condition and handle it */
13672            if (ic->next
13673              && ic->next->op == IFX
13674              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13675                genIfx (ic->next,ic);
13676           else
13677             genIpop (ic);
13678           break; 
13679             
13680         case CALL:
13681           genCall (ic);
13682           break;
13683             
13684         case PCALL:
13685           genPcall (ic);
13686           break;
13687             
13688         case FUNCTION:
13689           genFunction (ic);
13690           break;
13691             
13692         case ENDFUNCTION:
13693           genEndFunction (ic);
13694           break;
13695             
13696         case RETURN:
13697           genRet (ic);
13698           break;
13699             
13700         case LABEL:
13701           genLabel (ic);
13702           break;
13703             
13704         case GOTO:
13705           genGoto (ic);
13706           break;
13707             
13708         case '+' :
13709           pic16_genPlus (ic) ;
13710           break;
13711             
13712         case '-' :
13713           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13714             pic16_genMinus (ic);
13715           break;
13716
13717         case '*' :
13718           genMult (ic);
13719           break;
13720             
13721         case '/' :
13722           genDiv (ic) ;
13723           break;
13724             
13725         case '%' :
13726           genMod (ic);
13727           break;
13728             
13729         case '>' :
13730           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13731           break;
13732             
13733         case '<' :
13734           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13735           break;
13736             
13737         case LE_OP:
13738         case GE_OP:
13739         case NE_OP:
13740           /* note these two are xlated by algebraic equivalence
13741            * during parsing SDCC.y */
13742           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13743             "got '>=' or '<=' shouldn't have come here");
13744           break;
13745
13746         case EQ_OP:
13747           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13748           break;            
13749             
13750         case AND_OP:
13751           genAndOp (ic);
13752           break;
13753             
13754         case OR_OP:
13755           genOrOp (ic);
13756           break;
13757             
13758         case '^' :
13759           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13760           break;
13761             
13762         case '|' :
13763           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13764           break;
13765             
13766         case BITWISEAND:
13767           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13768           break;
13769             
13770         case INLINEASM:
13771           genInline (ic);
13772           break;
13773             
13774         case RRC:
13775           genRRC (ic);
13776           break;
13777             
13778         case RLC:
13779           genRLC (ic);
13780           break;
13781             
13782         case GETHBIT:
13783           genGetHbit (ic);
13784           break;
13785             
13786         case LEFT_OP:
13787           genLeftShift (ic);
13788           break;
13789             
13790         case RIGHT_OP:
13791           genRightShift (ic);
13792           break;
13793             
13794         case GET_VALUE_AT_ADDRESS:
13795           genPointerGet(ic);
13796           break;
13797             
13798         case '=' :
13799           if (POINTER_SET(ic))
13800             genPointerSet(ic);
13801           else
13802             genAssign(ic);
13803           break;
13804             
13805         case IFX:
13806           genIfx (ic,NULL);
13807           break;
13808             
13809         case ADDRESS_OF:
13810           genAddrOf (ic);
13811           break;
13812             
13813         case JUMPTABLE:
13814           genJumpTab (ic);
13815           break;
13816             
13817         case CAST:
13818           genCast (ic);
13819           break;
13820             
13821         case RECEIVE:
13822           genReceive(ic);
13823           break;
13824             
13825         case SEND:
13826           addSet(&_G.sendSet,ic);
13827           break;
13828
13829         case DUMMY_READ_VOLATILE:
13830           genDummyRead (ic);
13831           break;
13832
13833         default :
13834           ic = ic;
13835       }
13836     }
13837
13838
13839     /* now we are ready to call the
13840        peep hole optimizer */
13841     if (!options.nopeep)
13842       peepHole (&lineHead);
13843
13844     /* now do the actual printing */
13845     printLine (lineHead, codeOutFile);
13846
13847 #ifdef PCODE_DEBUG
13848     DFPRINTF((stderr,"printing pBlock\n\n"));
13849     pic16_printpBlock(stdout,pb);
13850 #endif
13851
13852     return;
13853 }
13854