* src/pic/glue.h: added pic14aopLiteral prototype
[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     pic16_emitcode("","%s:",sym->rname);
3709     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3710
3711     {
3712       absSym *ab;
3713
3714         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3715           if(!strcmp(ab->name, sym->rname)) {
3716             pic16_pBlockConvert2Absolute(pb);
3717             break;
3718           }
3719         }
3720     }
3721
3722     if(IFFUNC_ISNAKED(ftype)) {
3723       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3724       return;
3725     }
3726         
3727     /* if critical function then turn interrupts off */
3728     if (IFFUNC_ISCRITICAL(ftype)) {
3729       //pic16_emitcode("clr","ea");
3730     }
3731
3732     currFunc = sym;             /* update the currFunc symbol */
3733     _G.fregsUsed = sym->regsUsed;
3734     _G.sregsAlloc = newBitVect(128);
3735     
3736
3737     /* if this is an interrupt service routine then
3738      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3739     if (IFFUNC_ISISR(sym->type)) {
3740         _G.usefastretfie = 1;   /* use shadow registers by default */
3741         
3742         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3743         if(!FUNC_ISSHADOWREGS(sym->type)) {
3744           /* do not save WREG,STATUS,BSR for high priority interrupts
3745            * because they are stored in the hardware shadow registers already */
3746           _G.usefastretfie = 0;
3747           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3748           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3749           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3750         }
3751
3752         /* these should really be optimized somehow, because not all
3753          * interrupt handlers modify them */
3754         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3755         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3756         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3757         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3758         
3759 //        pic16_pBlockConvert2ISR(pb);
3760     }
3761
3762     /* emit code to setup stack frame if user enabled,
3763      * and function is not main() */
3764     
3765 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3766     if(strcmp(sym->name, "main")) {
3767       if(0 
3768         || !options.ommitFramePtr 
3769 //        || sym->regsUsed
3770         || IFFUNC_ARGS(sym->type)
3771         || FUNC_HASSTACKPARM(sym->etype)
3772         ) {
3773         /* setup the stack frame */
3774         if(STACK_MODEL_LARGE)
3775           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3776         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3777
3778         if(STACK_MODEL_LARGE)
3779           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3780         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3781       }
3782     }
3783
3784     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3785           && sym->stack) {
3786
3787       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3788
3789       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3790       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3791       emitSKPC;
3792       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3793     }
3794           
3795     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3796       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3797         _G.useWreg = 0;
3798       else
3799         _G.useWreg = 1;
3800     } else
3801       _G.useWreg = 0;
3802
3803     /* if callee-save to be used for this function
3804      * then save the registers being used in this function */
3805 //    if (IFFUNC_CALLEESAVES(sym->type))
3806     if(strcmp(sym->name, "main")) {
3807       int i;
3808
3809         /* if any registers used */
3810         if (sym->regsUsed) {
3811                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3812
3813           if(!xinst) {
3814             /* save the registers used */
3815             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3816             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3817               if (bitVectBitValue(sym->regsUsed,i)) {
3818 #if 0
3819                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3820 #endif
3821                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3822                 _G.nRegsSaved++;
3823
3824                 if(!pic16_regWithIdx(i)->wasUsed) {
3825                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3826                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3827                   pic16_regWithIdx(i)->wasUsed = 1;
3828                 }
3829               }
3830             }
3831           } else {
3832             
3833             /* xinst */
3834             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3835             for(i=0;i<sym->regsUsed->size;i++) {
3836               if(bitVectBitValue(sym->regsUsed, i)) {
3837                 _G.nRegsSaved++;
3838               }
3839             }
3840                         
3841 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3842           }
3843
3844           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3845
3846         }
3847     }
3848         
3849     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3850 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3851 }
3852
3853 /*-----------------------------------------------------------------*/
3854 /* genEndFunction - generates epilogue for functions               */
3855 /*-----------------------------------------------------------------*/
3856 static void genEndFunction (iCode *ic)
3857 {
3858   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3859
3860     FENTRY;
3861
3862     if(IFFUNC_ISNAKED(sym->type)) {
3863       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3864       return;
3865     }
3866
3867     _G.stack_lat = 0;
3868
3869     /* add code for ISCRITICAL */
3870     if(IFFUNC_ISCRITICAL(sym->type)) {
3871       /* if critical function, turn on interrupts */
3872       
3873       /* TODO: add code here -- VR */
3874     }
3875     
3876 //    sym->regsUsed = _G.fregsUsed;
3877     
3878     /* now we need to restore the registers */
3879     /* if any registers used */
3880
3881     /* first restore registers that might be used for stack access */
3882     if(_G.sregsAllocSet) {
3883     regs *sr;
3884     
3885       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3886       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3887         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3888       }
3889     }
3890
3891     if (strcmp(sym->name, "main") && sym->regsUsed) {
3892       int i;
3893
3894         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3895         /* restore registers used */
3896         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3897         for ( i = sym->regsUsed->size; i >= 0; i--) {
3898           if (bitVectBitValue(sym->regsUsed,i)) {
3899             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3900             _G.nRegsSaved--;
3901           }
3902         }
3903         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3904     }
3905
3906       
3907
3908     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3909           && sym->stack) {
3910       if (sym->stack == 1) {
3911         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3912         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3913       } else {
3914         // we have to add more than one...
3915         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3916         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3917         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3918         emitSKPNC;
3919         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3920         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3921         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3922       }
3923     }
3924
3925     if(strcmp(sym->name, "main")) {
3926       if(0
3927         || !options.ommitFramePtr
3928 //        || sym->regsUsed
3929         || IFFUNC_ARGS(sym->type)
3930         || FUNC_HASSTACKPARM(sym->etype)
3931         ) {
3932         /* restore stack frame */
3933         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3934         if(STACK_MODEL_LARGE)
3935           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3936       }
3937     }
3938
3939     _G.useWreg = 0;
3940
3941     if (IFFUNC_ISISR(sym->type)) {
3942       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3943       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3944       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3945       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3946
3947       if(!FUNC_ISSHADOWREGS(sym->type)) {
3948         /* do not restore interrupt vector for WREG,STATUS,BSR
3949          * for high priority interrupt, see genFunction */
3950         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3951         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3952         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3953       }
3954 //      _G.interruptvector = 0;         /* sanity check */
3955
3956
3957       /* if debug then send end of function */
3958 /*      if (options.debug && currFunc)  */
3959       if (currFunc) {
3960         debugFile->writeEndFunction (currFunc, ic, 1);
3961       }
3962         
3963       if(_G.usefastretfie)
3964         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3965       else
3966         pic16_emitpcodeNULLop(POC_RETFIE);
3967
3968       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3969       
3970       _G.usefastretfie = 0;
3971       return;
3972     }
3973
3974     if (IFFUNC_ISCRITICAL(sym->type)) {
3975       pic16_emitcode("setb","ea");
3976     }
3977
3978     /* if debug then send end of function */
3979     if (currFunc) {
3980       debugFile->writeEndFunction (currFunc, ic, 1);
3981     }
3982
3983     /* insert code to restore stack frame, if user enabled it
3984      * and function is not main() */
3985          
3986
3987     pic16_emitpcodeNULLop(POC_RETURN);
3988
3989     /* Mark the end of a function */
3990     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3991 }
3992
3993
3994 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3995 {
3996   unsigned long lit=1;
3997   operand *op;
3998   
3999     op = IC_LEFT(ic);
4000   
4001     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4002     if(AOP_TYPE(op) == AOP_LIT) {
4003       if(!IS_FLOAT(operandType( op ))) {
4004         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4005       } else {
4006         union {
4007           unsigned long lit_int;
4008           float lit_float;
4009         } info;
4010         
4011         /* take care if literal is a float */
4012         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4013         lit = info.lit_int;
4014       }
4015     }
4016
4017     if (AOP_TYPE(op) == AOP_LIT) {
4018       /* FIXME: broken for
4019        *   char __at(0x456) foo;
4020        *   return &foo;
4021        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4022       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4023     } else if (AOP_TYPE(op) == AOP_PCODE
4024                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4025       /* char *s= "aaa"; return s; */
4026       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4027        *      that the generic pointer is interpreted correctly
4028        *      as referring to __code space, but this is fragile! */
4029       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4030       /* XXX: should check that dest != WREG */
4031       pic16_emitpcode(POC_MOVWF, dest);
4032     } else {
4033       if(dest->type == PO_WREG && (offset == 0)) {
4034         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4035         return;
4036       }
4037       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4038     }
4039 }
4040
4041 /*-----------------------------------------------------------------*/
4042 /* genRet - generate code for return statement                     */
4043 /*-----------------------------------------------------------------*/
4044 static void genRet (iCode *ic)
4045 {
4046   int size;
4047   operand *left;
4048
4049     FENTRY;
4050         /* if we have no return value then
4051          * just generate the "ret" */
4052         
4053         if (!IC_LEFT(ic)) 
4054                 goto jumpret;       
4055     
4056         /* we have something to return then
4057          * move the return value into place */
4058         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4059         size = AOP_SIZE(IC_LEFT(ic));
4060
4061         if(size <= 4) {
4062           if(size>3)
4063             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4064           
4065           if(size>2)
4066             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4067
4068           if(size>1)
4069             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4070           
4071           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4072
4073         } else {
4074                 /* >32-bits, setup stack and FSR0 */
4075                 while (size--) {
4076 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4077 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4078
4079                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4080
4081 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4082                         GpsuedoStkPtr++;
4083                 }
4084                         
4085                 /* setup FSR0 */
4086                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4087                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4088
4089                 if(STACK_MODEL_LARGE) {
4090                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4091                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4092                 } else {
4093                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4094                 }
4095         }
4096                                 
4097 #if 0
4098         /* old code, left here for reference -- VR */    
4099         while (size--) {
4100           char *l ;
4101
4102                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4103                         /* #NOCHANGE */
4104                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4105                         pic16_emitpcomment("push %s",l);
4106                         pushed++;
4107                 } else {
4108                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4109                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4110                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4111                         
4112                         if (strcmp(fReturn[offset],l)) {
4113                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4114                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4115                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4116                                 } else {
4117                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4118                                 }
4119                                 
4120                                 if(size) {
4121                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4122                                 }
4123                                 offset++;
4124                         }
4125                 }
4126         }    
4127
4128         if (pushed) {
4129                 while(pushed) {
4130                         pushed--;
4131                         if (strcmp(fReturn[pushed],"a"))
4132                                 pic16_emitcode("pop",fReturn[pushed]);
4133                         else
4134                                 pic16_emitcode("pop","acc");
4135                 }
4136         }
4137 #endif
4138
4139
4140         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4141     
4142 jumpret:
4143         /* generate a jump to the return label
4144          * if the next is not the return statement */
4145         if (!(ic->next && ic->next->op == LABEL
4146                 && IC_LABEL(ic->next) == returnLabel)) {
4147         
4148                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4149                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4150         }
4151 }
4152
4153 /*-----------------------------------------------------------------*/
4154 /* genLabel - generates a label                                    */
4155 /*-----------------------------------------------------------------*/
4156 static void genLabel (iCode *ic)
4157 {
4158   FENTRY;
4159
4160   /* special case never generate */
4161   if (IC_LABEL(ic) == entryLabel)
4162     return ;
4163
4164   pic16_emitpLabel(IC_LABEL(ic)->key);
4165 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4166 }
4167
4168 /*-----------------------------------------------------------------*/
4169 /* genGoto - generates a goto                                      */
4170 /*-----------------------------------------------------------------*/
4171 //tsd
4172 static void genGoto (iCode *ic)
4173 {
4174   FENTRY;
4175   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4176 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4177 }
4178
4179
4180 /*-----------------------------------------------------------------*/
4181 /* genMultbits :- multiplication of bits                           */
4182 /*-----------------------------------------------------------------*/
4183 static void genMultbits (operand *left, 
4184                          operand *right, 
4185                          operand *result)
4186 {
4187   FENTRY;
4188
4189   if(!pic16_sameRegs(AOP(result),AOP(right)))
4190     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4191
4192   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4193   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4194   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4195
4196 }
4197
4198
4199 /*-----------------------------------------------------------------*/
4200 /* genMultOneByte : 8 bit multiplication & division                */
4201 /*-----------------------------------------------------------------*/
4202 static void genMultOneByte (operand *left,
4203                             operand *right,
4204                             operand *result)
4205 {
4206
4207   FENTRY;
4208   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4209   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4210
4211   /* (if two literals, the value is computed before) */
4212   /* if one literal, literal on the right */
4213   if (AOP_TYPE(left) == AOP_LIT){
4214     operand *t = right;
4215     right = left;
4216     left = t;
4217   }
4218
4219         /* size is already checked in genMult == 1 */
4220 //      size = AOP_SIZE(result);
4221
4222         if (AOP_TYPE(right) == AOP_LIT){
4223                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4224                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4225                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4226                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4227         } else {
4228                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4229                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4230                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4231                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4232         }
4233         
4234         pic16_genMult8X8_n (left, right,result);
4235 }
4236
4237 #if 0
4238 /*-----------------------------------------------------------------*/
4239 /* genMultOneWord : 16 bit multiplication                          */
4240 /*-----------------------------------------------------------------*/
4241 static void genMultOneWord (operand *left,
4242                             operand *right,
4243                             operand *result)
4244 {
4245   FENTRY;
4246   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4247   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4248
4249   /* (if two literals, the value is computed before)
4250    * if one literal, literal on the right */
4251   if (AOP_TYPE(left) == AOP_LIT){
4252     operand *t = right;
4253     right = left;
4254     left = t;
4255   }
4256
4257   /* size is checked already == 2 */
4258 //  size = AOP_SIZE(result);
4259
4260   if (AOP_TYPE(right) == AOP_LIT) {
4261     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4262       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4263       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4264       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4265   } else {
4266     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4267       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4268       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4269       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4270   }
4271         
4272   pic16_genMult16X16_16(left, right,result);
4273 }
4274 #endif
4275
4276 #if 0
4277 /*-----------------------------------------------------------------*/
4278 /* genMultOneLong : 32 bit multiplication                          */
4279 /*-----------------------------------------------------------------*/
4280 static void genMultOneLong (operand *left,
4281                             operand *right,
4282                             operand *result)
4283 {
4284   FENTRY;
4285   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4286   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4287
4288   /* (if two literals, the value is computed before)
4289    * if one literal, literal on the right */
4290   if (AOP_TYPE(left) == AOP_LIT){
4291     operand *t = right;
4292     right = left;
4293     left = t;
4294   }
4295
4296   /* size is checked already == 4 */
4297 //  size = AOP_SIZE(result);
4298
4299   if (AOP_TYPE(right) == AOP_LIT) {
4300     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4301         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4302         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4303         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4304   } else {
4305     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4306         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4307         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4308         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4309   }
4310         
4311   pic16_genMult32X32_32(left, right,result);
4312 }
4313 #endif
4314
4315
4316
4317 /*-----------------------------------------------------------------*/
4318 /* genMult - generates code for multiplication                     */
4319 /*-----------------------------------------------------------------*/
4320 static void genMult (iCode *ic)
4321 {
4322   operand *left = IC_LEFT(ic);
4323   operand *right = IC_RIGHT(ic);
4324   operand *result= IC_RESULT(ic);   
4325
4326     FENTRY;
4327         /* assign the amsops */
4328         pic16_aopOp (left,ic,FALSE);
4329         pic16_aopOp (right,ic,FALSE);
4330         pic16_aopOp (result,ic,TRUE);
4331
4332         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4333
4334         /* special cases first *
4335         * both are bits */
4336         if (AOP_TYPE(left) == AOP_CRY
4337                 && AOP_TYPE(right)== AOP_CRY) {
4338                 genMultbits(left,right,result);
4339           goto release ;
4340         }
4341
4342         /* if both are of size == 1 */
4343         if(AOP_SIZE(left) == 1
4344                 && AOP_SIZE(right) == 1) {
4345                 genMultOneByte(left,right,result);
4346           goto release ;
4347         }
4348
4349 #if 0
4350         /* if both are of size == 2 */
4351         if(AOP_SIZE(left) == 2
4352                 && AOP_SIZE(right) == 2) {
4353                 genMultOneWord(left, right, result);
4354           goto release;
4355         }
4356         
4357         /* if both are of size == 4 */
4358         if(AOP_SIZE(left) == 4
4359                 && AOP_SIZE(right) == 4) {
4360                 genMultOneLong(left, right, result);
4361           goto release;
4362         }
4363 #endif
4364
4365         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4366         assert( !"Multiplication should have been transformed into function call!" );
4367
4368         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4369
4370
4371         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4372         /* should have been converted to function call */
4373         assert(0) ;
4374
4375 release :
4376         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4377         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4378         pic16_freeAsmop(result,NULL,ic,TRUE); 
4379 }
4380
4381 #if 0
4382 /*-----------------------------------------------------------------*/
4383 /* genDivbits :- division of bits                                  */
4384 /*-----------------------------------------------------------------*/
4385 static void genDivbits (operand *left, 
4386                         operand *right, 
4387                         operand *result)
4388 {
4389   char *l;
4390
4391     FENTRY;
4392     /* the result must be bit */    
4393     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4394     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4395
4396     MOVA(l);    
4397
4398     pic16_emitcode("div","ab");
4399     pic16_emitcode("rrc","a");
4400     pic16_aopPut(AOP(result),"c",0);
4401 }
4402
4403 /*-----------------------------------------------------------------*/
4404 /* genDivOneByte : 8 bit division                                  */
4405 /*-----------------------------------------------------------------*/
4406 static void genDivOneByte (operand *left,
4407                            operand *right,
4408                            operand *result)
4409 {
4410   sym_link *opetype = operandType(result);
4411   char *l ;
4412   symbol *lbl ;
4413   int size,offset;
4414
4415         /* result = divident / divisor
4416          * - divident may be a register or a literal,
4417          * - divisor may be a register or a literal,
4418          * so there are 3 cases (literal / literal is optimized
4419          * by the front-end) to handle.
4420          * In addition we must handle signed and unsigned, which
4421          * result in 6 final different cases -- VR */
4422
4423     FENTRY;
4424     
4425     size = AOP_SIZE(result) - 1;
4426     offset = 1;
4427     /* signed or unsigned */
4428     if (SPEC_USIGN(opetype)) {
4429       pCodeOp *pct1,    /* count */
4430                 *pct2,  /* reste */
4431                 *pct3;  /* temp */
4432       symbol *label1, *label2, *label3;;
4433
4434
4435         /* unsigned is easy */
4436
4437         pct1 = pic16_popGetTempReg(1);
4438         pct2 = pic16_popGetTempReg(1);
4439         pct3 = pic16_popGetTempReg(1);
4440         
4441         label1 = newiTempLabel(NULL);
4442         label2 = newiTempLabel(NULL);
4443         label3 = newiTempLabel(NULL);
4444
4445         /* the following algorithm is extracted from divuint.c */
4446
4447         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4448         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4449         
4450         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4451
4452         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4453         
4454         pic16_emitpLabel(label1->key);
4455         
4456         emitCLRC;
4457         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4458
4459
4460         emitCLRC;
4461         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4462         
4463
4464         emitSKPNC;
4465         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4466         
4467         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4468         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4469         
4470         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4471         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4472         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4473         
4474         pic16_emitpLabel( label3->key );
4475         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4476         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4477         
4478         
4479
4480         pic16_emitpLabel(label2->key);
4481         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4482         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4483         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4484         
4485         /* result is in wreg */
4486         if(AOP_TYPE(result) != AOP_ACC)
4487                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4488
4489         pic16_popReleaseTempReg( pct3, 1);
4490         pic16_popReleaseTempReg( pct2, 1);
4491         pic16_popReleaseTempReg( pct1, 1);
4492
4493         return ;
4494     }
4495
4496     /* signed is a little bit more difficult */
4497
4498     /* save the signs of the operands */
4499     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4500     MOVA(l);    
4501     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4502     pic16_emitcode("push","acc"); /* save it on the stack */
4503
4504     /* now sign adjust for both left & right */
4505     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4506     MOVA(l);       
4507     lbl = newiTempLabel(NULL);
4508     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4509     pic16_emitcode("cpl","a");   
4510     pic16_emitcode("inc","a");
4511     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4512     pic16_emitcode("mov","b,a");
4513
4514     /* sign adjust left side */
4515     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4516     MOVA(l);
4517
4518     lbl = newiTempLabel(NULL);
4519     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4520     pic16_emitcode("cpl","a");
4521     pic16_emitcode("inc","a");
4522     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4523
4524     /* now the division */
4525     pic16_emitcode("div","ab");
4526     /* we are interested in the lower order
4527     only */
4528     pic16_emitcode("mov","b,a");
4529     lbl = newiTempLabel(NULL);
4530     pic16_emitcode("pop","acc");   
4531     /* if there was an over flow we don't 
4532     adjust the sign of the result */
4533     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4534     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4535     CLRC;
4536     pic16_emitcode("clr","a");
4537     pic16_emitcode("subb","a,b");
4538     pic16_emitcode("mov","b,a");
4539     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4540
4541     /* now we are done */
4542     pic16_aopPut(AOP(result),"b",0);
4543     if(size > 0){
4544         pic16_emitcode("mov","c,b.7");
4545         pic16_emitcode("subb","a,acc");   
4546     }
4547     while (size--)
4548         pic16_aopPut(AOP(result),"a",offset++);
4549
4550 }
4551 #endif
4552
4553 /*-----------------------------------------------------------------*/
4554 /* genDiv - generates code for division                            */
4555 /*-----------------------------------------------------------------*/
4556 static void genDiv (iCode *ic)
4557 {
4558     operand *left = IC_LEFT(ic);
4559     operand *right = IC_RIGHT(ic);
4560     operand *result= IC_RESULT(ic);   
4561     int negated = 0;
4562     int leftVal = 0, rightVal = 0;
4563     int signedLits = 0;
4564     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4565     int op = 0;
4566     
4567         /* Division is a very lengthy algorithm, so it is better
4568          * to call support routines than inlining algorithm.
4569          * Division functions written here just in case someone
4570          * wants to inline and not use the support libraries -- VR */
4571
4572     FENTRY;
4573     
4574     /* assign the amsops */
4575     pic16_aopOp (left,ic,FALSE);
4576     pic16_aopOp (right,ic,FALSE);
4577     pic16_aopOp (result,ic,TRUE);
4578
4579     if (ic->op == '/')
4580       op = 0;
4581     else if (ic->op == '%')
4582       op = 1;
4583     else
4584       assert( !"invalid operation requested in genDivMod" );
4585
4586     /* get literal values */
4587     if (IS_VALOP(left)) {
4588       leftVal = (int)floatFromVal( OP_VALUE(left) );
4589       assert( leftVal >= -128 && leftVal < 256 );
4590       if (leftVal < 0) { signedLits++; }
4591     }
4592     if (IS_VALOP(right)) {
4593       rightVal = (int)floatFromVal( OP_VALUE(right) );
4594       assert( rightVal >= -128 && rightVal < 256 );
4595       if (rightVal < 0) { signedLits++; }
4596     }
4597
4598     /* We should only come here to convert all
4599      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4600      * with exactly one operand being s8_t into
4601      * u8_t x u8_t -> u8_t. All other cases should have been
4602      * turned into calls to support routines beforehand... */
4603     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4604         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4605     {
4606       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4607           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4608       {
4609         /* Both operands are signed or negative, use _divschar
4610          * instead of _divuchar */
4611         pushaop(AOP(right), 0);
4612         pushaop(AOP(left), 0);
4613
4614         /* call _divschar */
4615         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4616
4617         {
4618           symbol *sym;
4619           sym = newSymbol( functions[op][0], 0 );
4620           sym->used++;
4621           strcpy(sym->rname, functions[op][0]);
4622           checkAddSym(&externs, sym);
4623         }
4624
4625         /* assign result */
4626         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4627         if (AOP_SIZE(result) > 1)
4628         {
4629           pic16_emitpcode(POC_MOVFF,
4630               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4631                 pic16_popGet(AOP(result), 1)));
4632           /* sign extend */
4633           pic16_addSign(result, 2, 1);
4634         }
4635
4636         /* clean up stack */
4637         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4638         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4639
4640         goto release;
4641       }
4642       
4643       /* push right operand */
4644       if (IS_VALOP(right)) {
4645         if (rightVal < 0) {
4646           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4647           negated++;
4648         } else {
4649           pushaop(AOP(right), 0);
4650         }
4651       } else if (!IS_UNSIGNED(operandType(right))) {
4652         pic16_mov2w(AOP(right), 0);
4653         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4654         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4655         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4656         negated++;
4657       } else {
4658         pushaop(AOP(right), 0);
4659       }
4660
4661       /* push left operand */
4662       if (IS_VALOP(left)) {
4663         if (leftVal < 0) {
4664           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4665           negated++;
4666         } else {
4667           pushaop(AOP(left), 0);
4668         }
4669       } else if (!IS_UNSIGNED(operandType(left))) {
4670         pic16_mov2w(AOP(left),0);
4671         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4672         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4673         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4674         negated++;
4675       } else {
4676         pushaop(AOP(left), 0);
4677       }
4678       
4679       /* call _divuchar */
4680       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4681
4682       {
4683         symbol *sym;
4684         sym = newSymbol( functions[op][1], 0 );
4685         sym->used++;
4686         strcpy(sym->rname, functions[op][1]);
4687         checkAddSym(&externs, sym);
4688       }
4689
4690       /* Revert negation(s) from above.
4691        * This is inefficient: if both operands are negative, this
4692        * should not touch WREG. However, determining that exactly
4693        * one operand was negated costs at least 3 instructions,
4694        * so there is nothing to be gained here, is there?
4695        *
4696        * I negate WREG because either operand might share registers with
4697        * result, so assigning first might destroy an operand. */
4698       
4699       /* For the modulus operator, (a/b)*b == a shall hold.
4700        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4701        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
4702        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
4703        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
4704        * Only invert the result if the left operand is negative (sigh).
4705        */
4706       if (AOP_SIZE(result) <= 1 || !negated)
4707       {
4708         if (ic->op == '/')
4709         {
4710           if (IS_VALOP(right)) {
4711             if (rightVal < 0) {
4712               /* we negated this operand above */
4713               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4714             }
4715           } else if (!IS_UNSIGNED(operandType(right))) {
4716             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4717             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4718           }
4719         }
4720
4721         if (IS_VALOP(left)) {
4722           if (leftVal < 0) {
4723             /* we negated this operand above */
4724             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4725           }
4726         } else if (!IS_UNSIGNED(operandType(left))) {
4727           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4728           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4729         }
4730
4731         /* Move result to destination. */
4732         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4733
4734         /* Zero-extend:  no operand was signed (or result is just a byte). */
4735         pic16_addSign(result, 1, 0);
4736       } else {
4737         assert( AOP_SIZE(result) > 1 );
4738         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4739         if (ic->op == '/')
4740         {
4741           if (IS_VALOP(right)) {
4742             if (rightVal < 0) {
4743               /* we negated this operand above */
4744               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4745             }
4746           } else if (!IS_UNSIGNED(operandType(right))) {
4747             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4748             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4749           }
4750         }
4751
4752         if (IS_VALOP(left)) {
4753           if (leftVal < 0) {
4754             /* we negated this operand above */
4755             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4756           }
4757         } else if (!IS_UNSIGNED(operandType(left))) {
4758           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4759           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4760         }
4761
4762         /* Move result to destination. */
4763         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4764
4765         /* Negate result if required. */
4766         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4767         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4768
4769         /* Sign-extend. */
4770         pic16_addSign(result, 2, 1);
4771       }
4772
4773       /* clean up stack */
4774       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4775       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4776       goto release;
4777     }
4778
4779 #if 0
4780     /* special cases first */
4781     /* both are bits */
4782     if (AOP_TYPE(left) == AOP_CRY &&
4783         AOP_TYPE(right)== AOP_CRY) {
4784         genDivbits(left,right,result);
4785         goto release ;
4786     }
4787
4788     /* if both are of size == 1 */
4789     if (AOP_SIZE(left) == 1 &&
4790         AOP_SIZE(right) == 1 ) {
4791         genDivOneByte(left,right,result);
4792         goto release ;
4793     }
4794 #endif
4795
4796     /* should have been converted to function call */
4797     assert(0);
4798 release :
4799     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4800     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4801     pic16_freeAsmop(result,NULL,ic,TRUE); 
4802 }
4803
4804 #if 0
4805 /*-----------------------------------------------------------------*/
4806 /* genModbits :- modulus of bits                                   */
4807 /*-----------------------------------------------------------------*/
4808 static void genModbits (operand *left, 
4809                         operand *right, 
4810                         operand *result)
4811 {
4812   char *l;
4813
4814     FENTRY;  
4815     
4816     werror(W_POSSBUG2, __FILE__, __LINE__);
4817     /* the result must be bit */    
4818     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4819     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4820
4821     MOVA(l);       
4822
4823     pic16_emitcode("div","ab");
4824     pic16_emitcode("mov","a,b");
4825     pic16_emitcode("rrc","a");
4826     pic16_aopPut(AOP(result),"c",0);
4827 }
4828
4829 /*-----------------------------------------------------------------*/
4830 /* genModOneByte : 8 bit modulus                                   */
4831 /*-----------------------------------------------------------------*/
4832 static void genModOneByte (operand *left,
4833                            operand *right,
4834                            operand *result)
4835 {
4836   sym_link *opetype = operandType(result);
4837   char *l ;
4838   symbol *lbl ;
4839
4840     FENTRY;
4841     werror(W_POSSBUG2, __FILE__, __LINE__);
4842
4843     /* signed or unsigned */
4844     if (SPEC_USIGN(opetype)) {
4845         /* unsigned is easy */
4846         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4847         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4848         MOVA(l);    
4849         pic16_emitcode("div","ab");
4850         pic16_aopPut(AOP(result),"b",0);
4851         return ;
4852     }
4853
4854     /* signed is a little bit more difficult */
4855
4856     /* save the signs of the operands */
4857     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4858     MOVA(l);
4859
4860     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4861     pic16_emitcode("push","acc"); /* save it on the stack */
4862
4863     /* now sign adjust for both left & right */
4864     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4865     MOVA(l);
4866
4867     lbl = newiTempLabel(NULL);
4868     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4869     pic16_emitcode("cpl","a");   
4870     pic16_emitcode("inc","a");
4871     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4872     pic16_emitcode("mov","b,a"); 
4873
4874     /* sign adjust left side */
4875     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4876     MOVA(l);
4877
4878     lbl = newiTempLabel(NULL);
4879     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4880     pic16_emitcode("cpl","a");   
4881     pic16_emitcode("inc","a");
4882     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4883
4884     /* now the multiplication */
4885     pic16_emitcode("div","ab");
4886     /* we are interested in the lower order
4887     only */
4888     lbl = newiTempLabel(NULL);
4889     pic16_emitcode("pop","acc");   
4890     /* if there was an over flow we don't 
4891     adjust the sign of the result */
4892     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4893     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4894     CLRC ;
4895     pic16_emitcode("clr","a");
4896     pic16_emitcode("subb","a,b");
4897     pic16_emitcode("mov","b,a");
4898     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4899
4900     /* now we are done */
4901     pic16_aopPut(AOP(result),"b",0);
4902
4903 }
4904 #endif
4905
4906 /*-----------------------------------------------------------------*/
4907 /* genMod - generates code for division                            */
4908 /*-----------------------------------------------------------------*/
4909 static void genMod (iCode *ic)
4910 {
4911   /* Task deferred to genDiv */
4912   genDiv(ic);
4913 #if 0
4914   operand *left = IC_LEFT(ic);
4915   operand *right = IC_RIGHT(ic);
4916   operand *result= IC_RESULT(ic);  
4917
4918     FENTRY;
4919     
4920     /* assign the amsops */
4921     pic16_aopOp (left,ic,FALSE);
4922     pic16_aopOp (right,ic,FALSE);
4923     pic16_aopOp (result,ic,TRUE);
4924
4925     /* special cases first */
4926     /* both are bits */
4927     if (AOP_TYPE(left) == AOP_CRY &&
4928         AOP_TYPE(right)== AOP_CRY) {
4929         genModbits(left,right,result);
4930         goto release ;
4931     }
4932
4933     /* if both are of size == 1 */
4934     if (AOP_SIZE(left) == 1 &&
4935         AOP_SIZE(right) == 1 ) {
4936         genModOneByte(left,right,result);
4937         goto release ;
4938     }
4939
4940     /* should have been converted to function call */
4941     assert(0);
4942
4943 release :
4944     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4945     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4946     pic16_freeAsmop(result,NULL,ic,TRUE); 
4947 #endif
4948 }
4949
4950 /*-----------------------------------------------------------------*/
4951 /* genIfxJump :- will create a jump depending on the ifx           */
4952 /*-----------------------------------------------------------------*/
4953 /*
4954   note: May need to add parameter to indicate when a variable is in bit space.
4955 */
4956 static void genIfxJump (iCode *ic, char *jval)
4957 {
4958   FENTRY;
4959   
4960     /* if true label then we jump if condition
4961     supplied is true */
4962     if ( IC_TRUE(ic) ) {
4963
4964         if(strcmp(jval,"a") == 0)
4965           emitSKPZ;
4966         else if (strcmp(jval,"c") == 0)
4967           emitSKPNC;
4968         else {
4969           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4970           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4971         }
4972
4973         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4974         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4975
4976     }
4977     else {
4978         /* false label is present */
4979         if(strcmp(jval,"a") == 0)
4980           emitSKPNZ;
4981         else if (strcmp(jval,"c") == 0)
4982           emitSKPC;
4983         else {
4984           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4985           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4986         }
4987
4988         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4989         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4990
4991     }
4992
4993
4994     /* mark the icode as generated */
4995     ic->generated = 1;
4996 }
4997
4998 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4999 {
5000   FENTRY;
5001   
5002     /* if true label then we jump if condition
5003     supplied is true */
5004     if ( IC_TRUE(ic) ) {
5005       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
5006       pic16_emitpcode(POC_BTFSC, jop);
5007
5008       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5009       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5010
5011     } else {
5012       /* false label is present */
5013       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5014       pic16_emitpcode(POC_BTFSS, jop);
5015           
5016       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5017       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5018     }
5019
5020
5021     /* mark the icode as generated */
5022     ic->generated = 1;
5023 }
5024
5025 #if 0
5026 // not needed ATM
5027
5028 /*-----------------------------------------------------------------*/
5029 /* genSkip                                                         */
5030 /*-----------------------------------------------------------------*/
5031 static void genSkip(iCode *ifx,int status_bit)
5032 {
5033   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5034   if(!ifx)
5035     return;
5036
5037   if ( IC_TRUE(ifx) ) {
5038     switch(status_bit) {
5039     case 'z':
5040       emitSKPNZ;
5041       break;
5042
5043     case 'c':
5044       emitSKPNC;
5045       break;
5046
5047     case 'd':
5048       emitSKPDC;
5049       break;
5050
5051     }
5052
5053     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5054     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5055
5056   } else {
5057
5058     switch(status_bit) {
5059
5060     case 'z':
5061       emitSKPZ;
5062       break;
5063
5064     case 'c':
5065       emitSKPC;
5066       break;
5067
5068     case 'd':
5069       emitSKPDC;
5070       break;
5071     }
5072     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5073     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5074
5075   }
5076
5077 }
5078 #endif
5079
5080 /*-----------------------------------------------------------------*/
5081 /* genSkipc                                                        */
5082 /*-----------------------------------------------------------------*/
5083 static void genSkipc(resolvedIfx *rifx)
5084 {
5085   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5086   
5087   if(!rifx)
5088     return;
5089
5090   if(rifx->condition)
5091     emitSKPNC;
5092   else
5093     emitSKPC;
5094
5095   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5096   rifx->generated = 1;
5097 }
5098
5099 #if !(USE_SIMPLE_GENCMP)
5100 /*-----------------------------------------------------------------*/
5101 /* genSkipz2                                                       */
5102 /*-----------------------------------------------------------------*/
5103 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5104 {
5105   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5106   
5107   if(!rifx)
5108     return;
5109
5110   if( (rifx->condition ^ invert_condition) & 1)
5111     emitSKPZ;
5112   else
5113     emitSKPNZ;
5114
5115   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5116   rifx->generated = 1;
5117 }
5118 #endif
5119
5120 #if 0
5121 /*-----------------------------------------------------------------*/
5122 /* genSkipz                                                        */
5123 /*-----------------------------------------------------------------*/
5124 static void genSkipz(iCode *ifx, int condition)
5125 {
5126   if(!ifx)
5127     return;
5128
5129   if(condition)
5130     emitSKPNZ;
5131   else
5132     emitSKPZ;
5133
5134   if ( IC_TRUE(ifx) )
5135     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5136   else
5137     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5138
5139   if ( IC_TRUE(ifx) )
5140     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5141   else
5142     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5143
5144 }
5145 #endif
5146
5147 #if !(USE_SIMPLE_GENCMP)
5148 /*-----------------------------------------------------------------*/
5149 /* genSkipCond                                                     */
5150 /*-----------------------------------------------------------------*/
5151 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5152 {
5153   if(!rifx)
5154     return;
5155
5156   if(rifx->condition)
5157     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5158   else
5159     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5160
5161
5162   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5163   rifx->generated = 1;
5164 }
5165 #endif
5166
5167 #if 0
5168 /*-----------------------------------------------------------------*/
5169 /* genChkZeroes :- greater or less than comparison                 */
5170 /*     For each byte in a literal that is zero, inclusive or the   */
5171 /*     the corresponding byte in the operand with W                */
5172 /*     returns true if any of the bytes are zero                   */
5173 /*-----------------------------------------------------------------*/
5174 static int genChkZeroes(operand *op, int lit,  int size)
5175 {
5176
5177   int i;
5178   int flag =1;
5179
5180   while(size--) {
5181     i = (lit >> (size*8)) & 0xff;
5182
5183     if(i==0) {
5184       if(flag) 
5185         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5186       else
5187         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5188       flag = 0;
5189     }
5190   }
5191
5192   return (flag==0);
5193 }
5194 #endif
5195
5196
5197 /*-----------------------------------------------------------------*/
5198 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
5199 /*                  aop (if it's NOT a literal) or from lit (if    */
5200 /*                  aop is a literal)                              */
5201 /*-----------------------------------------------------------------*/
5202 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5203   if (aop->type == AOP_LIT) {
5204     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5205   } else {
5206     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5207   }
5208 }
5209
5210 /*-----------------------------------------------------------------*/
5211 /* genCmp :- greater or less than comparison                       */
5212 /*-----------------------------------------------------------------*/
5213
5214 #if USE_SIMPLE_GENCMP           /* { */
5215
5216 /* genCmp performs a left < right comparison, stores
5217  * the outcome in result (if != NULL) and generates
5218  * control flow code for the ifx (if != NULL).
5219  *
5220  * This version leaves in sequences like
5221  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5222  * which should be optmized by the peephole
5223  * optimizer - RN 2005-01-01 */
5224 static void genCmp (operand *left,operand *right,
5225                     operand *result, iCode *ifx, int sign)
5226 {
5227   resolvedIfx rIfx;
5228   int size;
5229   int offs;
5230   symbol *templbl;
5231   operand *dummy;
5232   unsigned long lit;
5233   unsigned long mask;
5234   int performedLt;
5235
5236   FENTRY;
5237   
5238   assert (left && right);
5239   assert (AOP_SIZE(left) == AOP_SIZE(right));
5240
5241   size = AOP_SIZE(right) - 1;
5242   mask = (0x100UL << (size*8)) - 1;
5243   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5244   performedLt = 1;
5245   templbl = NULL;
5246   lit = 0;
5247   
5248   resolveIfx (&rIfx, ifx);
5249
5250   /* handle for special cases */
5251   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5252       return;
5253
5254   /**********************************************************************
5255    * handle bits - bit compares are promoted to int compares seemingly! *
5256    **********************************************************************/
5257 #if 0
5258   // THIS IS COMPLETELY UNTESTED!
5259   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5260     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5261     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5262     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5263
5264     emitSETC;
5265     // 1 < {0,1} is false --> clear C by skipping the next instruction
5266     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5267     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5268     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5269     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5270     emitCLRC; // only skipped for left=0 && right=1
5271
5272     goto correct_result_in_carry;
5273   } // if
5274 #endif
5275
5276   /*************************************************
5277    * make sure that left is register (or the like) *
5278    *************************************************/
5279   if (!isAOP_REGlike(left)) {
5280     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5281     assert (isAOP_LIT(left));
5282     assert (isAOP_REGlike(right));
5283     // swap left and right
5284     // left < right <==> right > left <==> (right >= left + 1)
5285     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5286
5287     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5288       // MAXVALUE < right? always false
5289       if (performedLt) emitCLRC; else emitSETC;
5290       goto correct_result_in_carry;
5291     } // if
5292
5293     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5294     // that's why we handled it above.
5295     lit++;
5296
5297     dummy = left;
5298     left = right;
5299     right = dummy;
5300
5301     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5302   } else if (isAOP_LIT(right)) {
5303     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5304   } // if
5305
5306   assert (isAOP_REGlike(left)); // left must be register or the like
5307   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5308
5309   /*************************************************
5310    * special cases go here                         *
5311    *************************************************/
5312
5313   if (isAOP_LIT(right)) {
5314     if (!sign) {
5315       // unsigned comparison to a literal
5316       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5317       if (lit == 0) {
5318         // unsigned left < 0? always false
5319         if (performedLt) emitCLRC; else emitSETC;
5320         goto correct_result_in_carry;
5321       }
5322     } else {
5323       // signed comparison to a literal
5324       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5325       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5326         // signed left < 0x80000000? always false
5327         if (performedLt) emitCLRC; else emitSETC;
5328         goto correct_result_in_carry;
5329       } else if (lit == 0) {
5330         // compare left < 0; set CARRY if SIGNBIT(left) is set
5331         if (performedLt) emitSETC; else emitCLRC;
5332         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5333         if (performedLt) emitCLRC; else emitSETC;
5334         goto correct_result_in_carry;
5335       }
5336     } // if (!sign)
5337   } // right is literal
5338
5339   /*************************************************
5340    * perform a general case comparison             *
5341    * make sure we get CARRY==1 <==> left >= right  *
5342    *************************************************/
5343   // compare most significant bytes
5344   //DEBUGpc ("comparing bytes at offset %d", size);
5345   if (!sign) {
5346     // unsigned comparison
5347     mov2w_regOrLit (AOP(right), lit, size);
5348     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5349   } else {
5350     // signed comparison
5351     // (add 2^n to both operands then perform an unsigned comparison)
5352     if (isAOP_LIT(right)) {
5353       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5354       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5355
5356       if (litbyte == 0x80) {
5357         // left >= 0x80 -- always true, but more bytes to come
5358         pic16_mov2w (AOP(left), size);
5359         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5360         emitSETC;
5361       } else {
5362         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5363         pic16_mov2w (AOP(left), size);
5364         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5365         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5366       } // if
5367     } else {
5368       /* using PRODL as a temporary register here */
5369       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5370       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5371       pic16_mov2w (AOP(left), size);
5372       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5373       pic16_emitpcode (POC_MOVWF, pctemp);
5374       pic16_mov2w (AOP(right), size);
5375       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5376       pic16_emitpcode (POC_SUBFW, pctemp);
5377       //pic16_popReleaseTempReg(pctemp, 1);
5378     }
5379   } // if (!sign)
5380
5381   // compare remaining bytes (treat as unsigned case from above)
5382   templbl = newiTempLabel ( NULL );
5383   offs = size;
5384   while (offs--) {
5385     //DEBUGpc ("comparing bytes at offset %d", offs);
5386     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5387     mov2w_regOrLit (AOP(right), lit, offs);
5388     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5389   } // while (offs)
5390   pic16_emitpLabel (templbl->key);
5391   goto result_in_carry;
5392
5393 result_in_carry:
5394   
5395   /****************************************************
5396    * now CARRY contains the result of the comparison: *
5397    * SUBWF sets CARRY iff                             *
5398    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5399    * (F=left, W=right)                                *
5400    ****************************************************/
5401
5402   if (performedLt) {
5403     if (result && AOP_TYPE(result) != AOP_CRY) {
5404       // value will be stored
5405       emitTOGC;
5406     } else {
5407       // value wil only be used in the following genSkipc()
5408       rIfx.condition ^= 1;
5409     }
5410   } // if
5411
5412 correct_result_in_carry:
5413
5414   // assign result to variable (if neccessary)
5415   if (result && AOP_TYPE(result) != AOP_CRY) {
5416     //DEBUGpc ("assign result");
5417     size = AOP_SIZE(result);
5418     while (size--) {
5419       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5420     } // while
5421     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5422   } // if (result)
5423
5424   // perform conditional jump
5425   if (ifx) {
5426     //DEBUGpc ("generate control flow");
5427     genSkipc (&rIfx);
5428     ifx->generated = 1;
5429   } // if
5430 }
5431
5432 #elif 1         /* } */
5433                 /* { */
5434       /* original code */
5435 static void genCmp (operand *left,operand *right,
5436                     operand *result, iCode *ifx, int sign)
5437 {
5438   int size; //, offset = 0 ;
5439   unsigned long lit = 0L,i = 0;
5440   resolvedIfx rFalseIfx;
5441   //  resolvedIfx rTrueIfx;
5442   symbol *truelbl;
5443   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5444 /*
5445   if(ifx) {
5446     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5447     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5448   }
5449 */
5450
5451   FENTRY;
5452   
5453   resolveIfx(&rFalseIfx,ifx);
5454   truelbl  = newiTempLabel(NULL);
5455   size = max(AOP_SIZE(left),AOP_SIZE(right));
5456
5457   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5458
5459 #define _swapp
5460
5461   /* if literal is on the right then swap with left */
5462   if ((AOP_TYPE(right) == AOP_LIT)) {
5463     operand *tmp = right ;
5464     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5465     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5466 #ifdef _swapp
5467
5468     lit = (lit - 1) & mask;
5469     right = left;
5470     left = tmp;
5471     rFalseIfx.condition ^= 1;
5472 #endif
5473
5474   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5475     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5476   }
5477
5478
5479   //if(IC_TRUE(ifx) == NULL)
5480   /* if left & right are bit variables */
5481   if (AOP_TYPE(left) == AOP_CRY &&
5482       AOP_TYPE(right) == AOP_CRY ) {
5483     assert (0 && "bit variables used in genCmp");
5484     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5485     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5486   } else {
5487     /* subtract right from left if at the
5488        end the carry flag is set then we know that
5489        left is greater than right */
5490
5491     symbol *lbl  = newiTempLabel(NULL);
5492
5493 #if 0
5494         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5495                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5496 #endif
5497
5498 #ifndef _swapp
5499     if(AOP_TYPE(right) == AOP_LIT) {
5500
5501       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5502
5503       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5504
5505       /* special cases */
5506
5507       if(lit == 0) {
5508
5509         if(sign != 0) 
5510           genSkipCond(&rFalseIfx,left,size-1,7);
5511         else 
5512           /* no need to compare to 0...*/
5513           /* NOTE: this is a de-generate compare that most certainly 
5514            *       creates some dead code. */
5515           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5516
5517         if(ifx) ifx->generated = 1;
5518         return;
5519
5520       }
5521       size--;
5522
5523       if(size == 0) {
5524         //i = (lit >> (size*8)) & 0xff;
5525         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5526         
5527         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5528
5529         i = ((0-lit) & 0xff);
5530         if(sign) {
5531           if( i == 0x81) { 
5532             /* lit is 0x7f, all signed chars are less than
5533              * this except for 0x7f itself */
5534             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5535             genSkipz2(&rFalseIfx,0);
5536           } else {
5537             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5538             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5539             genSkipc(&rFalseIfx);
5540           }
5541
5542         } else {
5543           if(lit == 1) {
5544             genSkipz2(&rFalseIfx,1);
5545           } else {
5546             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5547             genSkipc(&rFalseIfx);
5548           }
5549         }
5550
5551         if(ifx) ifx->generated = 1;
5552         return;
5553       }
5554
5555       /* chars are out of the way. now do ints and longs */
5556
5557
5558       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5559         
5560       /* special cases */
5561
5562       if(sign) {
5563
5564         if(lit == 0) {
5565           genSkipCond(&rFalseIfx,left,size,7);
5566           if(ifx) ifx->generated = 1;
5567           return;
5568         }
5569
5570         if(lit <0x100) {
5571           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5572
5573           //rFalseIfx.condition ^= 1;
5574           //genSkipCond(&rFalseIfx,left,size,7);
5575           //rFalseIfx.condition ^= 1;
5576
5577           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5578           if(rFalseIfx.condition)
5579             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5580           else
5581             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5582
5583           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5584           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5585           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5586
5587           while(size > 1)
5588             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5589
5590           if(rFalseIfx.condition) {
5591             emitSKPZ;
5592             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5593
5594           } else {
5595             emitSKPNZ;
5596           }
5597
5598           genSkipc(&rFalseIfx);
5599           pic16_emitpLabel(truelbl->key);
5600           if(ifx) ifx->generated = 1;
5601           return;
5602
5603         }
5604
5605         if(size == 1) {
5606
5607           if( (lit & 0xff) == 0) {
5608             /* lower byte is zero */
5609             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5610             i = ((lit >> 8) & 0xff) ^0x80;
5611             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5612             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5613             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5614             genSkipc(&rFalseIfx);
5615
5616
5617             if(ifx) ifx->generated = 1;
5618             return;
5619
5620           }
5621         } else {
5622           /* Special cases for signed longs */
5623           if( (lit & 0xffffff) == 0) {
5624             /* lower byte is zero */
5625             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5626             i = ((lit >> 8*3) & 0xff) ^0x80;
5627             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5628             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5629             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5630             genSkipc(&rFalseIfx);
5631
5632
5633             if(ifx) ifx->generated = 1;
5634             return;
5635
5636           }
5637
5638         }
5639
5640
5641         if(lit & (0x80 << (size*8))) {
5642           /* lit is negative */
5643           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5644
5645           //genSkipCond(&rFalseIfx,left,size,7);
5646
5647           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5648
5649           if(rFalseIfx.condition)
5650             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5651           else
5652             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5653
5654
5655         } else {
5656           /* lit is positive */
5657           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5658           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5659           if(rFalseIfx.condition)
5660             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5661           else
5662             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5663
5664         }
5665
5666         /*
5667           This works, but is only good for ints.
5668           It also requires a "known zero" register.
5669           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5670           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5671           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5672           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5673           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5674           genSkipc(&rFalseIfx);
5675
5676           pic16_emitpLabel(truelbl->key);
5677           if(ifx) ifx->generated = 1;
5678           return;
5679         **/
5680           
5681         /* There are no more special cases, so perform a general compare */
5682   
5683         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5684         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5685
5686         while(size--) {
5687
5688           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5689           emitSKPNZ;
5690           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5691         }
5692         //rFalseIfx.condition ^= 1;
5693         genSkipc(&rFalseIfx);
5694
5695         pic16_emitpLabel(truelbl->key);
5696
5697         if(ifx) ifx->generated = 1;
5698         return;
5699
5700
5701       }
5702
5703
5704       /* sign is out of the way. So now do an unsigned compare */
5705       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5706
5707
5708       /* General case - compare to an unsigned literal on the right.*/
5709
5710       i = (lit >> (size*8)) & 0xff;
5711       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5712       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5713       while(size--) {
5714         i = (lit >> (size*8)) & 0xff;
5715
5716         if(i) {
5717           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5718           emitSKPNZ;
5719           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5720         } else {
5721           /* this byte of the lit is zero, 
5722            *if it's not the last then OR in the variable */
5723           if(size)
5724             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5725         }
5726       }
5727
5728
5729       pic16_emitpLabel(lbl->key);
5730 //      pic16_emitpLabel(truelbl->key);
5731       //if(emitFinalCheck)
5732       genSkipc(&rFalseIfx);
5733       if(sign)
5734         pic16_emitpLabel(truelbl->key);
5735
5736       if(ifx) ifx->generated = 1;
5737       return;
5738
5739
5740     }
5741 #endif  // _swapp
5742
5743     if(AOP_TYPE(left) == AOP_LIT) {
5744       //symbol *lbl = newiTempLabel(NULL);
5745
5746       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5747
5748
5749       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5750
5751       /* Special cases */
5752       if((lit == 0) && (sign == 0)){
5753
5754         size--;
5755         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5756         while(size) 
5757           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5758
5759         genSkipz2(&rFalseIfx,0);
5760         if(ifx) ifx->generated = 1;
5761         return;
5762       }
5763
5764       if(size==1) {
5765         /* Special cases */
5766         lit &= 0xff;
5767         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5768           /* degenerate compare can never be true */
5769           if(rFalseIfx.condition == 0)
5770             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5771
5772           if(ifx) ifx->generated = 1;
5773           return;
5774         }
5775
5776         if(sign) {
5777           /* signed comparisons to a literal byte */
5778
5779           int lp1 = (lit+1) & 0xff;
5780
5781           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5782           switch (lp1) {
5783           case 0:
5784             rFalseIfx.condition ^= 1;
5785             genSkipCond(&rFalseIfx,right,0,7);
5786             break;
5787           case 0x7f:
5788             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5789             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5790             genSkipz2(&rFalseIfx,1);
5791             break;
5792           default:
5793             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5794             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5795             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5796             rFalseIfx.condition ^= 1;
5797             genSkipc(&rFalseIfx);
5798             break;
5799           }
5800         } else {
5801           /* unsigned comparisons to a literal byte */
5802
5803           switch(lit & 0xff ) {
5804           case 0:
5805             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5806             genSkipz2(&rFalseIfx,0);
5807             break;
5808           case 0x7f:
5809             rFalseIfx.condition ^= 1;
5810             genSkipCond(&rFalseIfx,right,0,7);
5811             break;
5812
5813           default:
5814             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5815             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5816             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5817             rFalseIfx.condition ^= 1;
5818             if (AOP_TYPE(result) == AOP_CRY)
5819               genSkipc(&rFalseIfx);
5820             else {
5821               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5822               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5823             }         
5824             break;
5825           }
5826         }
5827
5828         if(ifx) ifx->generated = 1;
5829         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5830                 goto check_carry;
5831         return;
5832
5833       } else {
5834
5835         /* Size is greater than 1 */
5836
5837         if(sign) {
5838           int lp1 = lit+1;
5839
5840           size--;
5841
5842           if(lp1 == 0) {
5843             /* this means lit = 0xffffffff, or -1 */
5844
5845
5846             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5847             rFalseIfx.condition ^= 1;
5848             genSkipCond(&rFalseIfx,right,size,7);
5849             if(ifx) ifx->generated = 1;
5850
5851             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5852               goto check_carry;
5853
5854             return;
5855           }
5856
5857           if(lit == 0) {
5858             int s = size;
5859
5860             if(rFalseIfx.condition) {
5861               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5862               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5863             }
5864
5865             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5866             while(size--)
5867               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5868
5869
5870             emitSKPZ;
5871             if(rFalseIfx.condition) {
5872               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5873               pic16_emitpLabel(truelbl->key);
5874             }else {
5875               rFalseIfx.condition ^= 1;
5876               genSkipCond(&rFalseIfx,right,s,7);
5877             }
5878
5879             if(ifx) ifx->generated = 1;
5880
5881             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5882               goto check_carry;
5883
5884             return;
5885           }
5886
5887           if((size == 1) &&  (0 == (lp1&0xff))) {
5888             /* lower byte of signed word is zero */
5889             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5890             i = ((lp1 >> 8) & 0xff) ^0x80;
5891             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5892             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5893             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5894
5895             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5896               emitTOGC;
5897               if(ifx) ifx->generated = 1;
5898               goto check_carry;
5899             } else {
5900               rFalseIfx.condition ^= 1;
5901               genSkipc(&rFalseIfx);
5902               if(ifx) ifx->generated = 1;
5903             }
5904
5905             return;
5906           }
5907
5908           if(lit & (0x80 << (size*8))) {
5909             /* Lit is less than zero */
5910             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5911             //rFalseIfx.condition ^= 1;
5912             //genSkipCond(&rFalseIfx,left,size,7);
5913             //rFalseIfx.condition ^= 1;
5914             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5915             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5916
5917             if(rFalseIfx.condition)
5918               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5919             else
5920               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5921
5922
5923           } else {
5924             /* Lit is greater than or equal to zero */
5925             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5926             //rFalseIfx.condition ^= 1;
5927             //genSkipCond(&rFalseIfx,right,size,7);
5928             //rFalseIfx.condition ^= 1;
5929
5930             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5931             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5932
5933             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5934             if(rFalseIfx.condition)
5935               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5936             else
5937               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5938
5939           }
5940
5941           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5942           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5943
5944           while(size--) {
5945
5946             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5947             emitSKPNZ;
5948             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5949           }
5950           rFalseIfx.condition ^= 1;
5951           //rFalseIfx.condition = 1;
5952           genSkipc(&rFalseIfx);
5953
5954           pic16_emitpLabel(truelbl->key);
5955
5956           if(ifx) ifx->generated = 1;
5957
5958
5959           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5960             goto check_carry;
5961
5962           return;
5963           // end of if (sign)
5964         } else {
5965
5966           /* compare word or long to an unsigned literal on the right.*/
5967
5968
5969           size--;
5970           if(lit < 0xff) {
5971             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5972             switch (lit) {
5973             case 0:
5974               break; /* handled above */
5975 /*
5976             case 0xff:
5977               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5978               while(size--)
5979                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5980               genSkipz2(&rFalseIfx,0);
5981               break;
5982 */
5983             default:
5984               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5985               while(--size)
5986                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5987
5988               emitSKPZ;
5989               if(rFalseIfx.condition)
5990                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5991               else
5992                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5993
5994
5995               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5996               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5997
5998               rFalseIfx.condition ^= 1;
5999               genSkipc(&rFalseIfx);
6000             }
6001
6002             pic16_emitpLabel(truelbl->key);
6003
6004             if(ifx) ifx->generated = 1;
6005
6006             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6007               goto check_carry;
6008
6009             return;
6010           }
6011
6012
6013           lit++;
6014           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6015           i = (lit >> (size*8)) & 0xff;
6016
6017           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6018           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6019
6020           while(size--) {
6021             i = (lit >> (size*8)) & 0xff;
6022
6023             if(i) {
6024               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6025               emitSKPNZ;
6026               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6027             } else {
6028               /* this byte of the lit is zero, 
6029                * if it's not the last then OR in the variable */
6030               if(size)
6031                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6032             }
6033           }
6034
6035
6036           pic16_emitpLabel(lbl->key);
6037
6038           rFalseIfx.condition ^= 1;
6039
6040           genSkipc(&rFalseIfx);
6041         }
6042
6043         if(sign)
6044           pic16_emitpLabel(truelbl->key);
6045         if(ifx) ifx->generated = 1;
6046
6047             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6048               goto check_carry;
6049
6050         return;
6051       }
6052     }
6053     /* Compare two variables */
6054
6055     DEBUGpic16_emitcode(";sign","%d",sign);
6056
6057     size--;
6058     if(sign) {
6059       /* Sigh. thus sucks... */
6060       if(size) {
6061         pCodeOp *pctemp;
6062         
6063         pctemp = pic16_popGetTempReg(1);
6064         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6065         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6066         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6067         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6068         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6069         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6070         pic16_popReleaseTempReg(pctemp, 1);
6071       } else {
6072         /* Signed char comparison */
6073         /* Special thanks to Nikolai Golovchenko for this snippet */
6074         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6075         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6076         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6077         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6078         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6079         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6080
6081         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6082         genSkipc(&rFalseIfx);
6083           
6084         if(ifx) ifx->generated = 1;
6085
6086             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6087               goto check_carry;
6088
6089         return;
6090       }
6091
6092     } else {
6093
6094       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6095       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6096     }
6097
6098
6099     /* The rest of the bytes of a multi-byte compare */
6100     while (size) {
6101
6102       emitSKPZ;
6103       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6104       size--;
6105
6106       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6107       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6108
6109
6110     }
6111
6112     pic16_emitpLabel(lbl->key);
6113
6114     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6115     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6116         (AOP_TYPE(result) == AOP_REG)) {
6117       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6118       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6119     } else {
6120       genSkipc(&rFalseIfx);
6121     }         
6122     //genSkipc(&rFalseIfx);
6123     if(ifx) ifx->generated = 1;
6124
6125
6126             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6127               goto check_carry;
6128
6129     return;
6130
6131   }
6132
6133 check_carry:
6134   if ((AOP_TYPE(result) != AOP_CRY) 
6135         && AOP_SIZE(result)) {
6136     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6137
6138     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6139
6140     pic16_outBitC(result);
6141   } else {
6142     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6143     /* if the result is used in the next
6144        ifx conditional branch then generate
6145        code a little differently */
6146     if (ifx )
6147       genIfxJump (ifx,"c");
6148     else
6149       pic16_outBitC(result);
6150     /* leave the result in acc */
6151   }
6152
6153 }
6154
6155 #elif 0 /* VR version of genCmp() */    /* } else { */
6156
6157 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6158 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6159         operand *result, int offset, int invert_op)
6160 {
6161   /* add code here */
6162   
6163   /* check condition, > or < ?? */
6164   if(rIfx->condition != 0)invert_op ^= 1;
6165   
6166   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6167
6168   if(!ifx)invert_op ^= 1;
6169
6170   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6171       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6172   
6173   /* do selection */
6174   if(!invert_op)return POC_CPFSGT;
6175   else return POC_CPFSLT;
6176 }
6177
6178 static int compareAopfirstpass=1;
6179
6180 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6181             operand *oper, int offset, operand *result,
6182             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6183             symbol *tlbl)
6184 {
6185   int op;
6186   symbol *truelbl;
6187
6188   /* invert if there is a result to be loaded, in order to fit,
6189    * SETC/CLRC sequence */
6190   if(AOP_SIZE(result))invert_op ^= 1;
6191
6192 //  if(sign && !offset)invert_op ^= 1;
6193   
6194 //  if(sign)invert_op ^= 1;
6195   
6196   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6197
6198   if(AOP_SIZE(result) && compareAopfirstpass) {
6199     if(!ifx) {
6200       if(pcop2)
6201         pic16_emitpcode(POC_SETF, pcop2);
6202       else
6203         emitSETC;
6204     } else {
6205       if(pcop2)
6206         pic16_emitpcode(POC_CLRF, pcop2);
6207       else
6208         emitCLRC;
6209     }
6210   }
6211
6212   compareAopfirstpass = 0;
6213
6214       /* there is a bug when comparing operands with size > 1,
6215        * because higher bytes can be equal and test should be performed
6216        * to the next lower byte, current algorithm, considers operands
6217        * inequal in these cases! -- VR 20041107 */
6218
6219     
6220   if(pcop)
6221     pic16_emitpcode(op, pcop);
6222   else
6223     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6224
6225
6226   if((!sign || !offset) && AOP_SIZE(result)) {
6227     if(!ifx) {
6228       if(pcop2)
6229         pic16_emitpcode(POC_CLRF, pcop2);
6230         else
6231         emitCLRC;
6232     } else {
6233       if(pcop2)
6234         pic16_emitpcode(POC_SETF, pcop2);
6235       else
6236         emitSETC;
6237     }
6238     
6239     /* don't emit final branch (offset == 0) */
6240     if(offset) {
6241
6242       if(pcop2)
6243         pic16_emitpcode(POC_RRCF, pcop2);
6244
6245       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6246     }
6247   } else {
6248     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6249       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6250             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6251
6252       truelbl = newiTempLabel( NULL );
6253       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6254       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6255         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6256       else
6257         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6258       pic16_emitpLabel(truelbl->key);
6259     } else {
6260       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6261     }
6262   }
6263 }
6264
6265 static void genCmp (operand *left, operand *right,
6266                     operand *result, iCode *ifx, int sign)
6267 {
6268   int size, cmpop=1;
6269   long lit = 0L;
6270   resolvedIfx rFalseIfx;
6271   symbol *falselbl, *tlbl;
6272
6273     FENTRY;
6274     
6275     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6276
6277     resolveIfx(&rFalseIfx, ifx);
6278     size = max(AOP_SIZE(left), AOP_SIZE(right));
6279     
6280     /* if left & right are bit variables */
6281     if(AOP_TYPE(left) == AOP_CRY
6282       && AOP_TYPE(right) == AOP_CRY ) {
6283
6284         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6285         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6286         
6287         werror(W_POSSBUG2, __FILE__, __LINE__);
6288         exit(EXIT_FAILURE);
6289     }
6290     
6291     /* if literal is on the right then swap with left */
6292     if((AOP_TYPE(right) == AOP_LIT)) {
6293       operand *tmp = right ;
6294 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6295
6296         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6297
6298 //      lit = (lit - 1) & mask;
6299         right = left;
6300         left = tmp;
6301         rFalseIfx.condition ^= 1;               /* reverse compare */
6302     } else
6303     if ((AOP_TYPE(left) == AOP_LIT)) {
6304       /* float compares are handled by support functions */
6305       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6306     }
6307
6308     /* actual comparing algorithm */
6309 //    size = AOP_SIZE( right );
6310
6311     falselbl = newiTempLabel( NULL );
6312     if(AOP_TYPE(left) == AOP_LIT) {
6313       /* compare to literal */
6314       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6315       
6316       if(sign) {
6317         pCodeOp *pct, *pct2;
6318         symbol *tlbl1;
6319
6320         /* signed compare */
6321         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6322
6323         /* using PRODL:PRODH as a temporary register here */
6324         pct = pic16_popCopyReg(&pic16_pc_prodl);
6325         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6326         tlbl = newiTempLabel( NULL );
6327         
6328         /* first compare signs:
6329          *  a. if both are positive, compare just like unsigned
6330          *  b. if both are negative, invert cmpop, compare just like unsigned
6331          *  c. if different signs, determine the result directly */
6332
6333         size--;
6334
6335 #if 1
6336         /* { */
6337         tlbl1 = newiTempLabel( NULL );
6338 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6339
6340         if(lit > 0) {
6341
6342           /* literal is zero or positive:
6343            *  a. if carry is zero, too, continue compare,
6344            *  b. if carry is set, then continue depending on cmpop ^ condition:
6345            *    1. '<' return false (literal < variable),
6346            *    2. '>' return true (literal > variable) */
6347 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6348           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6349           
6350           
6351           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6352           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6353         } else 
6354         if(lit < 0) {
6355           
6356           /* literal is negative:
6357            *  a. if carry is set, too, continue compare,
6358            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6359            *    1. '<' return true (literal < variable),
6360            *    2. '>' return false (literal > variable) */
6361 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6362           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6363           
6364           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6365           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6366         }
6367 #if 1
6368         else {
6369           /* lit == 0 */
6370           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6371           
6372           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6373           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6374         }
6375 #endif
6376         
6377         
6378         pic16_emitpLabel( tlbl1->key );
6379 #endif  /* } */
6380
6381         compareAopfirstpass=1;
6382 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6383 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6384 //        pic16_emitpcode(POC_MOVWF, pct);
6385
6386 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6387         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6388 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6389         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6390
6391         /* generic case */        
6392           while( size-- ) {
6393 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6394 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6395 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6396 //            pic16_emitpcode(POC_MOVWF, pct);
6397
6398 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6399             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6400             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6401 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6402 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6403           }
6404         
6405         if(ifx)ifx->generated = 1;
6406
6407         if(AOP_SIZE(result)) {
6408           pic16_emitpLabel(tlbl->key);
6409           pic16_emitpLabel(falselbl->key);
6410           pic16_outBitOp( result, pct2 );
6411         } else {
6412           pic16_emitpLabel(tlbl->key);
6413         }
6414       } else {
6415
6416         /* unsigned compare */      
6417         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6418     
6419         compareAopfirstpass=1;
6420         while(size--) {
6421           
6422           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6423           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6424
6425         }
6426         if(ifx)ifx->generated = 1;
6427
6428         if(AOP_SIZE(result)) {
6429           pic16_emitpLabel(falselbl->key);
6430           pic16_outBitC( result );
6431         }
6432
6433       }
6434     } else {
6435       /* compare registers */
6436       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6437
6438
6439       if(sign) {
6440         pCodeOp *pct, *pct2;
6441         
6442         /* signed compare */
6443         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6444
6445         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6446         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6447         tlbl = newiTempLabel( NULL );
6448         
6449         compareAopfirstpass=1;
6450
6451         size--;
6452         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6453 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6454         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6455         pic16_emitpcode(POC_MOVWF, pct);
6456
6457         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6458 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6459         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6460
6461         /* WREG already holds left + 0x80 */
6462         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6463         
6464         while( size-- ) {
6465           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6466 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6467           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6468           pic16_emitpcode(POC_MOVWF, pct);
6469                 
6470           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6471 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6472           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6473
6474           /* WREG already holds left + 0x80 */
6475           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6476 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6477         }
6478         
6479         if(ifx)ifx->generated = 1;
6480
6481         if(AOP_SIZE(result)) {
6482           pic16_emitpLabel(tlbl->key);
6483           pic16_emitpLabel(falselbl->key);
6484           pic16_outBitOp( result, pct2 );
6485         } else {
6486           pic16_emitpLabel(tlbl->key);
6487         }
6488
6489       } else {
6490         /* unsigned compare */      
6491         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6492
6493         compareAopfirstpass=1;
6494         while(size--) {
6495           
6496           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6497           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6498
6499         }
6500
6501         if(ifx)ifx->generated = 1;
6502         if(AOP_SIZE(result)) {
6503
6504           pic16_emitpLabel(falselbl->key);
6505           pic16_outBitC( result );
6506         }
6507
6508       }
6509     }
6510 }
6511
6512 #endif  /* } */
6513
6514
6515
6516 /*-----------------------------------------------------------------*/
6517 /* genCmpGt :- greater than comparison                             */
6518 /*-----------------------------------------------------------------*/
6519 static void genCmpGt (iCode *ic, iCode *ifx)
6520 {
6521   operand *left, *right, *result;
6522   sym_link *letype , *retype;
6523   int sign ;
6524
6525     FENTRY;
6526     
6527     left = IC_LEFT(ic);
6528     right= IC_RIGHT(ic);
6529     result = IC_RESULT(ic);
6530
6531     letype = getSpec(operandType(left));
6532     retype =getSpec(operandType(right));
6533     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6534     /* assign the amsops */
6535     pic16_aopOp (left,ic,FALSE);
6536     pic16_aopOp (right,ic,FALSE);
6537     pic16_aopOp (result,ic,TRUE);
6538
6539     genCmp(right, left, result, ifx, sign);
6540
6541     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6542     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6543     pic16_freeAsmop(result,NULL,ic,TRUE); 
6544 }
6545
6546 /*-----------------------------------------------------------------*/
6547 /* genCmpLt - less than comparisons                                */
6548 /*-----------------------------------------------------------------*/
6549 static void genCmpLt (iCode *ic, iCode *ifx)
6550 {
6551   operand *left, *right, *result;
6552   sym_link *letype , *retype;
6553   int sign ;
6554
6555     FENTRY;
6556
6557     left = IC_LEFT(ic);
6558     right= IC_RIGHT(ic);
6559     result = IC_RESULT(ic);
6560
6561     letype = getSpec(operandType(left));
6562     retype =getSpec(operandType(right));
6563     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6564
6565     /* assign the amsops */
6566     pic16_aopOp (left,ic,FALSE);
6567     pic16_aopOp (right,ic,FALSE);
6568     pic16_aopOp (result,ic,TRUE);
6569
6570     genCmp(left, right, result, ifx, sign);
6571
6572     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6573     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6574     pic16_freeAsmop(result,NULL,ic,TRUE); 
6575 }
6576
6577 #if 0
6578 // not needed ATM
6579 // FIXME reenable literal optimisation when the pic16 port is stable
6580
6581 /*-----------------------------------------------------------------*/
6582 /* genc16bit2lit - compare a 16 bit value to a literal             */
6583 /*-----------------------------------------------------------------*/
6584 static void genc16bit2lit(operand *op, int lit, int offset)
6585 {
6586   int i;
6587
6588   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6589   if( (lit&0xff) == 0) 
6590     i=1;
6591   else
6592     i=0;
6593
6594   switch( BYTEofLONG(lit,i)) { 
6595   case 0:
6596     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6597     break;
6598   case 1:
6599     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6600     break;
6601   case 0xff:
6602     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6603     break;
6604   default:
6605     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6606     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6607   }
6608
6609   i ^= 1;
6610
6611   switch( BYTEofLONG(lit,i)) { 
6612   case 0:
6613     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6614     break;
6615   case 1:
6616     emitSKPNZ;
6617     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6618     break;
6619   case 0xff:
6620     emitSKPNZ;
6621     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6622     break;
6623   default:
6624     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6625     emitSKPNZ;
6626     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6627
6628   }
6629
6630 }
6631 #endif
6632
6633 #if 0
6634 // not needed ATM
6635 /*-----------------------------------------------------------------*/
6636 /* gencjneshort - compare and jump if not equal                    */
6637 /*-----------------------------------------------------------------*/
6638 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6639 {
6640   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6641   int offset = 0;
6642   int res_offset = 0;  /* the result may be a different size then left or right */
6643   int res_size = AOP_SIZE(result);
6644   resolvedIfx rIfx;
6645   symbol *lbl, *lbl_done;
6646
6647   unsigned long lit = 0L;
6648   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6649
6650   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6651   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6652   if(result)
6653     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6654   resolveIfx(&rIfx,ifx);
6655   lbl =  newiTempLabel(NULL);
6656   lbl_done =  newiTempLabel(NULL);
6657
6658
6659   /* if the left side is a literal or 
6660      if the right is in a pointer register and left 
6661      is not */
6662   if ((AOP_TYPE(left) == AOP_LIT) || 
6663       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6664     operand *t = right;
6665     right = left;
6666     left = t;
6667   }
6668   if(AOP_TYPE(right) == AOP_LIT)
6669     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6670
6671   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6672     preserve_result = 1;
6673
6674   if(result && !preserve_result)
6675     {
6676       int i;
6677       for(i = 0; i < AOP_SIZE(result); i++)
6678         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6679     }
6680
6681
6682   /* if the right side is a literal then anything goes */
6683   if (AOP_TYPE(right) == AOP_LIT &&
6684       AOP_TYPE(left) != AOP_DIR ) {
6685     switch(size) {
6686     case 2:
6687       genc16bit2lit(left, lit, 0);
6688       emitSKPZ;
6689       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6690       break;
6691     default:
6692       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6693       while (size--) {
6694         if(lit & 0xff) {
6695           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6696           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6697         } else {
6698           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6699         }
6700
6701         emitSKPZ;
6702         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6703         offset++;
6704         if(res_offset < res_size-1)
6705           res_offset++;
6706         lit >>= 8;
6707       }
6708       break;
6709     }
6710   }
6711
6712   /* if the right side is in a register or in direct space or
6713      if the left is a pointer register & right is not */    
6714   else if (AOP_TYPE(right) == AOP_REG ||
6715            AOP_TYPE(right) == AOP_DIR || 
6716            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6717            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6718     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6719     int lbl_key = lbl->key;
6720
6721     if(result) {
6722       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6723       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6724     }else {
6725       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6726       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6727               __FUNCTION__,__LINE__);
6728       return;
6729     }
6730    
6731 /*     switch(size) { */
6732 /*     case 2: */
6733 /*       genc16bit2lit(left, lit, 0); */
6734 /*       emitSKPNZ; */
6735 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6736 /*       break; */
6737 /*     default: */
6738     while (size--) {
6739       int emit_skip=1;
6740       if((AOP_TYPE(left) == AOP_DIR) && 
6741          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6742
6743         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6744         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6745
6746       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6747             
6748         switch (lit & 0xff) {
6749         case 0:
6750           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6751           break;
6752         case 1:
6753           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6754           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6755           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6756           emit_skip=0;
6757           break;
6758         case 0xff:
6759           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6760           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6761           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6762           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6763           emit_skip=0;
6764           break;
6765         default:
6766           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6767           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6768         }
6769         lit >>= 8;
6770
6771       } else {
6772         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6773       }
6774       if(emit_skip) {
6775         if(AOP_TYPE(result) == AOP_CRY) {
6776           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6777           if(rIfx.condition)
6778             emitSKPNZ;
6779           else
6780             emitSKPZ;
6781           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6782         } else {
6783           /* fix me. probably need to check result size too */
6784           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6785           if(rIfx.condition)
6786             emitSKPZ;
6787           else
6788             emitSKPNZ;
6789           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6790           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6791         }
6792         if(ifx)
6793           ifx->generated=1;
6794       }
6795       emit_skip++;
6796       offset++;
6797       if(res_offset < res_size-1)
6798         res_offset++;
6799     }
6800 /*       break; */
6801 /*     } */
6802   } else if(AOP_TYPE(right) == AOP_REG &&
6803             AOP_TYPE(left) != AOP_DIR){
6804
6805     while(size--) {
6806       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6807       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6808       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6809       if(rIfx.condition)
6810         emitSKPNZ;
6811       else
6812         emitSKPZ;
6813       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6814       offset++;
6815       if(res_offset < res_size-1)
6816         res_offset++;
6817     }
6818       
6819   }else{
6820     /* right is a pointer reg need both a & b */
6821     while(size--) {
6822       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6823       if(strcmp(l,"b"))
6824         pic16_emitcode("mov","b,%s",l);
6825       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6826       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6827       offset++;
6828     }
6829   }
6830
6831   if(result && preserve_result)
6832     {
6833       int i;
6834       for(i = 0; i < AOP_SIZE(result); i++)
6835         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6836     }
6837
6838   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6839
6840   if(result && preserve_result)
6841     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6842
6843   if(!rIfx.condition)
6844     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6845
6846   pic16_emitpLabel(lbl->key);
6847
6848   if(result && preserve_result)
6849     {
6850       int i;
6851       for(i = 0; i < AOP_SIZE(result); i++)
6852         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6853
6854       pic16_emitpLabel(lbl_done->key);
6855    }
6856
6857   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6858
6859   if(ifx)
6860     ifx->generated = 1;
6861 }
6862 #endif
6863
6864 #if 0
6865 /*-----------------------------------------------------------------*/
6866 /* gencjne - compare and jump if not equal                         */
6867 /*-----------------------------------------------------------------*/
6868 static void gencjne(operand *left, operand *right, iCode *ifx)
6869 {
6870     symbol *tlbl  = newiTempLabel(NULL);
6871
6872     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6873     gencjneshort(left, right, lbl);
6874
6875     pic16_emitcode("mov","a,%s",one);
6876     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6877     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6878     pic16_emitcode("clr","a");
6879     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6880
6881     pic16_emitpLabel(lbl->key);
6882     pic16_emitpLabel(tlbl->key);
6883
6884 }
6885 #endif
6886
6887
6888 /*-----------------------------------------------------------------*/
6889 /* is_LitOp - check if operand has to be treated as literal        */
6890 /*-----------------------------------------------------------------*/
6891 static bool is_LitOp(operand *op)
6892 {
6893   return ((AOP_TYPE(op) == AOP_LIT)
6894       || ( (AOP_TYPE(op) == AOP_PCODE)
6895           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6896               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6897 }
6898
6899 /*-----------------------------------------------------------------*/
6900 /* is_LitAOp - check if operand has to be treated as literal        */
6901 /*-----------------------------------------------------------------*/
6902 static bool is_LitAOp(asmop *aop)
6903 {
6904   return ((aop->type == AOP_LIT)
6905       || ( (aop->type == AOP_PCODE)
6906           && ( (aop->aopu.pcop->type == PO_LITERAL)
6907               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6908 }
6909
6910
6911
6912 /*-----------------------------------------------------------------*/
6913 /* genCmpEq - generates code for equal to                          */
6914 /*-----------------------------------------------------------------*/
6915 static void genCmpEq (iCode *ic, iCode *ifx)
6916 {
6917   operand *left, *right, *result;
6918   symbol *falselbl = newiTempLabel(NULL);
6919   symbol *donelbl = newiTempLabel(NULL);
6920
6921   int preserve_result = 0;
6922   int generate_result = 0;
6923   int i=0;
6924   unsigned long lit = -1;
6925
6926   FENTRY;
6927   
6928   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6929   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6930   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6931  
6932   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6933
6934   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6935     {
6936       werror(W_POSSBUG2, __FILE__, __LINE__);
6937       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6938       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6939       goto release;
6940     }
6941
6942   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6943     {
6944       operand *tmp = right ;
6945       right = left;
6946       left = tmp;
6947     }
6948
6949   if (AOP_TYPE(right) == AOP_LIT) {
6950     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6951   }
6952
6953   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6954     preserve_result = 1;
6955
6956   if(result && AOP_SIZE(result))
6957     generate_result = 1;
6958
6959   if(generate_result && !preserve_result)
6960     {
6961       for(i = 0; i < AOP_SIZE(result); i++)
6962         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6963     }
6964
6965   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6966   for(i=0; i < AOP_SIZE(left); i++)
6967     {
6968       if(AOP_TYPE(left) != AOP_ACC)
6969         {
6970           if(is_LitOp(left))
6971             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6972           else
6973             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6974         }
6975       if(is_LitOp(right)) {
6976         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6977           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6978         }
6979       } else
6980         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6981
6982       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6983     }
6984
6985   // result == true
6986
6987   if(generate_result && preserve_result)
6988     {
6989       for(i = 0; i < AOP_SIZE(result); i++)
6990         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6991     }
6992
6993   if(generate_result)
6994     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6995
6996   if(generate_result && preserve_result)
6997     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6998
6999   if(ifx && IC_TRUE(ifx))
7000     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7001
7002   if(ifx && IC_FALSE(ifx))
7003     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7004
7005   pic16_emitpLabel(falselbl->key);
7006
7007   // result == false
7008
7009   if(ifx && IC_FALSE(ifx))
7010     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7011
7012   if(generate_result && preserve_result)
7013     {
7014       for(i = 0; i < AOP_SIZE(result); i++)
7015         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7016     }
7017
7018   pic16_emitpLabel(donelbl->key);
7019
7020   if(ifx)
7021     ifx->generated = 1;
7022
7023 release:
7024   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7025   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7026   pic16_freeAsmop(result,NULL,ic,TRUE);
7027
7028 }
7029
7030
7031 #if 0
7032 // old version kept for reference
7033
7034 /*-----------------------------------------------------------------*/
7035 /* genCmpEq - generates code for equal to                          */
7036 /*-----------------------------------------------------------------*/
7037 static void genCmpEq (iCode *ic, iCode *ifx)
7038 {
7039     operand *left, *right, *result;
7040     unsigned long lit = 0L;
7041     int size,offset=0;
7042     symbol *falselbl  = newiTempLabel(NULL);
7043
7044
7045     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7046
7047     if(ifx)
7048       DEBUGpic16_emitcode ("; ifx is non-null","");
7049     else
7050       DEBUGpic16_emitcode ("; ifx is null","");
7051
7052     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7053     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7054     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7055
7056     size = max(AOP_SIZE(left),AOP_SIZE(right));
7057
7058     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7059
7060     /* if literal, literal on the right or 
7061     if the right is in a pointer register and left 
7062     is not */
7063     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7064         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7065       operand *tmp = right ;
7066       right = left;
7067       left = tmp;
7068     }
7069
7070
7071     if(ifx && !AOP_SIZE(result)){
7072         symbol *tlbl;
7073         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7074         /* if they are both bit variables */
7075         if (AOP_TYPE(left) == AOP_CRY &&
7076             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7077                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7078             if(AOP_TYPE(right) == AOP_LIT){
7079                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7080                 if(lit == 0L){
7081                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7082                     pic16_emitcode("cpl","c");
7083                 } else if(lit == 1L) {
7084                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7085                 } else {
7086                     pic16_emitcode("clr","c");
7087                 }
7088                 /* AOP_TYPE(right) == AOP_CRY */
7089             } else {
7090                 symbol *lbl = newiTempLabel(NULL);
7091                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7092                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7093                 pic16_emitcode("cpl","c");
7094                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7095             }
7096             /* if true label then we jump if condition
7097             supplied is true */
7098             tlbl = newiTempLabel(NULL);
7099             if ( IC_TRUE(ifx) ) {
7100                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7101                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7102             } else {
7103                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7104                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7105             }
7106             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7107
7108                 {
7109                 /* left and right are both bit variables, result is carry */
7110                         resolvedIfx rIfx;
7111               
7112                         resolveIfx(&rIfx,ifx);
7113
7114                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7115                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7116                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7117                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7118                         genSkipz2(&rIfx,0);
7119                 }
7120         } else {
7121
7122                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7123
7124                         /* They're not both bit variables. Is the right a literal? */
7125                         if(AOP_TYPE(right) == AOP_LIT) {
7126                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7127             
7128                         switch(size) {
7129
7130                                 case 1:
7131                                         switch(lit & 0xff) {
7132                                                 case 1:
7133                                                                 if ( IC_TRUE(ifx) ) {
7134                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7135                                                                         emitSKPNZ;
7136                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7137                                                                 } else {
7138                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7139                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7140                                                                 }
7141                                                                 break;
7142                                                 case 0xff:
7143                                                                 if ( IC_TRUE(ifx) ) {
7144                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7145                                                                         emitSKPNZ;
7146                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7147                                                                 } else {
7148                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7149                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7150                                                                 }
7151                                                                 break;
7152                                                 default:
7153                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7154                                                                 if(lit)
7155                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7156                                                                 genSkip(ifx,'z');
7157                                         } // switch lit
7158
7159
7160                                         /* end of size == 1 */
7161                                         break;
7162               
7163                                 case 2:
7164                                         genc16bit2lit(left,lit,offset);
7165                                         genSkip(ifx,'z');
7166                                         break;
7167                                         /* end of size == 2 */
7168
7169                                 default:
7170                                         /* size is 4 */
7171                                         if(lit==0) {
7172                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7173                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7174                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7175                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7176                                                 genSkip(ifx,'z');
7177                                         } else {
7178                                                 /* search for patterns that can be optimized */
7179
7180                                                 genc16bit2lit(left,lit,0);
7181                                                 lit >>= 16;
7182                                                 if(lit) {
7183                                                                 if(IC_TRUE(ifx))
7184                                                                 emitSKPZ; // if hi word unequal
7185                                                                 else
7186                                                                 emitSKPNZ; // if hi word equal
7187                                                                 // fail early
7188                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7189                                                         genc16bit2lit(left,lit,2);
7190                                                         genSkip(ifx,'z');
7191                                                 } else {
7192                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7193                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7194                                                         genSkip(ifx,'z');
7195                                                 }
7196                                         }
7197                                                 pic16_emitpLabel(falselbl->key);
7198                                                 break;
7199
7200                         } // switch size
7201           
7202                         ifx->generated = 1;
7203                         goto release ;
7204             
7205
7206           } else if(AOP_TYPE(right) == AOP_CRY ) {
7207             /* we know the left is not a bit, but that the right is */
7208             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7209             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7210                       pic16_popGet(AOP(right),offset));
7211             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7212
7213             /* if the two are equal, then W will be 0 and the Z bit is set
7214              * we could test Z now, or go ahead and check the high order bytes if
7215              * the variable we're comparing is larger than a byte. */
7216
7217             while(--size)
7218               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7219
7220             if ( IC_TRUE(ifx) ) {
7221               emitSKPNZ;
7222               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7223               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7224             } else {
7225               emitSKPZ;
7226               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7227               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7228             }
7229
7230           } else {
7231             /* They're both variables that are larger than bits */
7232             int s = size;
7233
7234             tlbl = newiTempLabel(NULL);
7235
7236             while(size--) {
7237               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7238               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7239
7240               if ( IC_TRUE(ifx) ) {
7241                 if(size) {
7242                   emitSKPZ;
7243                 
7244                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7245
7246                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7247                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7248                 } else {
7249                   emitSKPNZ;
7250
7251                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7252
7253
7254                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7255                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7256                 }
7257               } else {
7258                 emitSKPZ;
7259
7260                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7261
7262                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7263                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7264               }
7265               offset++;
7266             }
7267             if(s>1 && IC_TRUE(ifx)) {
7268               pic16_emitpLabel(tlbl->key);
7269               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7270             }
7271           }
7272         }
7273         /* mark the icode as generated */
7274         ifx->generated = 1;
7275         goto release ;
7276     }
7277
7278     /* if they are both bit variables */
7279     if (AOP_TYPE(left) == AOP_CRY &&
7280         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7281         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7282         if(AOP_TYPE(right) == AOP_LIT){
7283             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7284             if(lit == 0L){
7285                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7286                 pic16_emitcode("cpl","c");
7287             } else if(lit == 1L) {
7288                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7289             } else {
7290                 pic16_emitcode("clr","c");
7291             }
7292             /* AOP_TYPE(right) == AOP_CRY */
7293         } else {
7294             symbol *lbl = newiTempLabel(NULL);
7295             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7296             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7297             pic16_emitcode("cpl","c");
7298             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7299         }
7300         /* c = 1 if egal */
7301         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7302             pic16_outBitC(result);
7303             goto release ;
7304         }
7305         if (ifx) {
7306             genIfxJump (ifx,"c");
7307             goto release ;
7308         }
7309         /* if the result is used in an arithmetic operation
7310         then put the result in place */
7311         pic16_outBitC(result);
7312     } else {
7313       
7314       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7315       gencjne(left,right,result,ifx);
7316 /*
7317       if(ifx) 
7318         gencjne(left,right,newiTempLabel(NULL));
7319       else {
7320         if(IC_TRUE(ifx)->key)
7321           gencjne(left,right,IC_TRUE(ifx)->key);
7322         else
7323           gencjne(left,right,IC_FALSE(ifx)->key);
7324         ifx->generated = 1;
7325         goto release ;
7326       }
7327       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7328         pic16_aopPut(AOP(result),"a",0);
7329         goto release ;
7330       }
7331
7332       if (ifx) {
7333         genIfxJump (ifx,"a");
7334         goto release ;
7335       }
7336 */
7337       /* if the result is used in an arithmetic operation
7338          then put the result in place */
7339 /*
7340       if (AOP_TYPE(result) != AOP_CRY) 
7341         pic16_outAcc(result);
7342 */
7343       /* leave the result in acc */
7344     }
7345
7346 release:
7347     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7348     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7349     pic16_freeAsmop(result,NULL,ic,TRUE);
7350 }
7351 #endif
7352
7353 /*-----------------------------------------------------------------*/
7354 /* ifxForOp - returns the icode containing the ifx for operand     */
7355 /*-----------------------------------------------------------------*/
7356 static iCode *ifxForOp ( operand *op, iCode *ic )
7357 {
7358   FENTRY2;
7359
7360     /* if true symbol then needs to be assigned */
7361     if (IS_TRUE_SYMOP(op))
7362         return NULL ;
7363
7364     /* if this has register type condition and
7365     the next instruction is ifx with the same operand
7366     and live to of the operand is upto the ifx only then */
7367     if (ic->next
7368         && ic->next->op == IFX
7369         && IC_COND(ic->next)->key == op->key
7370         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7371         ) {
7372                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7373           return ic->next;
7374     }
7375
7376     /*
7377     if (ic->next &&
7378         ic->next->op == IFX &&
7379         IC_COND(ic->next)->key == op->key) {
7380       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7381       return ic->next;
7382     }
7383     */
7384
7385     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7386     if (ic->next &&
7387         ic->next->op == IFX)
7388       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7389
7390     if (ic->next &&
7391         ic->next->op == IFX &&
7392         IC_COND(ic->next)->key == op->key) {
7393       DEBUGpic16_emitcode ("; "," key is okay");
7394       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7395                            OP_SYMBOL(op)->liveTo,
7396                            ic->next->seq);
7397     }
7398
7399 #if 0
7400     /* the code below is completely untested
7401      * it just allows ulong2fs.c compile -- VR */
7402          
7403     ic = ic->next;
7404     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7405                                         __FILE__, __FUNCTION__, __LINE__);
7406         
7407     /* if this has register type condition and
7408     the next instruction is ifx with the same operand
7409     and live to of the operand is upto the ifx only then */
7410     if (ic->next &&
7411         ic->next->op == IFX &&
7412         IC_COND(ic->next)->key == op->key &&
7413         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7414         return ic->next;
7415
7416     if (ic->next &&
7417         ic->next->op == IFX &&
7418         IC_COND(ic->next)->key == op->key) {
7419       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7420       return ic->next;
7421     }
7422
7423     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7424                                         __FILE__, __FUNCTION__, __LINE__);
7425
7426 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7427 #endif
7428
7429     return NULL;
7430 }
7431 /*-----------------------------------------------------------------*/
7432 /* genAndOp - for && operation                                     */
7433 /*-----------------------------------------------------------------*/
7434 static void genAndOp (iCode *ic)
7435 {
7436   operand *left,*right, *result;
7437 /*     symbol *tlbl; */
7438
7439     FENTRY;
7440
7441     /* note here that && operations that are in an
7442     if statement are taken away by backPatchLabels
7443     only those used in arthmetic operations remain */
7444     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7445     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7446     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7447
7448     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7449
7450     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7451     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7452     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7453
7454     /* if both are bit variables */
7455 /*     if (AOP_TYPE(left) == AOP_CRY && */
7456 /*         AOP_TYPE(right) == AOP_CRY ) { */
7457 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7458 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7459 /*         pic16_outBitC(result); */
7460 /*     } else { */
7461 /*         tlbl = newiTempLabel(NULL); */
7462 /*         pic16_toBoolean(left);     */
7463 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7464 /*         pic16_toBoolean(right); */
7465 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7466 /*         pic16_outBitAcc(result); */
7467 /*     } */
7468
7469     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7470     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7471     pic16_freeAsmop(result,NULL,ic,TRUE);
7472 }
7473
7474
7475 /*-----------------------------------------------------------------*/
7476 /* genOrOp - for || operation                                      */
7477 /*-----------------------------------------------------------------*/
7478 /*
7479   tsd pic port -
7480   modified this code, but it doesn't appear to ever get called
7481 */
7482
7483 static void genOrOp (iCode *ic)
7484 {
7485   operand *left,*right, *result;
7486   symbol *tlbl;
7487
7488     FENTRY;  
7489
7490   /* note here that || operations that are in an
7491     if statement are taken away by backPatchLabels
7492     only those used in arthmetic operations remain */
7493     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7494     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7495     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7496
7497     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7498
7499     /* if both are bit variables */
7500     if (AOP_TYPE(left) == AOP_CRY &&
7501         AOP_TYPE(right) == AOP_CRY ) {
7502       pic16_emitcode("clrc","");
7503       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7504                AOP(left)->aopu.aop_dir,
7505                AOP(left)->aopu.aop_dir);
7506       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7507                AOP(right)->aopu.aop_dir,
7508                AOP(right)->aopu.aop_dir);
7509       pic16_emitcode("setc","");
7510
7511     } else {
7512         tlbl = newiTempLabel(NULL);
7513         pic16_toBoolean(left);
7514         emitSKPZ;
7515         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7516         pic16_toBoolean(right);
7517         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7518
7519         pic16_outBitAcc(result);
7520     }
7521
7522     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7523     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7524     pic16_freeAsmop(result,NULL,ic,TRUE);            
7525 }
7526
7527 /*-----------------------------------------------------------------*/
7528 /* isLiteralBit - test if lit == 2^n                               */
7529 /*-----------------------------------------------------------------*/
7530 static int isLiteralBit(unsigned long lit)
7531 {
7532     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7533     0x100L,0x200L,0x400L,0x800L,
7534     0x1000L,0x2000L,0x4000L,0x8000L,
7535     0x10000L,0x20000L,0x40000L,0x80000L,
7536     0x100000L,0x200000L,0x400000L,0x800000L,
7537     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7538     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7539     int idx;
7540     
7541     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7542     for(idx = 0; idx < 32; idx++)
7543         if(lit == pw[idx])
7544             return idx+1;
7545     return 0;
7546 }
7547
7548 /*-----------------------------------------------------------------*/
7549 /* continueIfTrue -                                                */
7550 /*-----------------------------------------------------------------*/
7551 static void continueIfTrue (iCode *ic)
7552 {
7553   FENTRY;
7554   if(IC_TRUE(ic))
7555     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7556   ic->generated = 1;
7557 }
7558
7559 /*-----------------------------------------------------------------*/
7560 /* jmpIfTrue -                                                     */
7561 /*-----------------------------------------------------------------*/
7562 static void jumpIfTrue (iCode *ic)
7563 {
7564   FENTRY;
7565   if(!IC_TRUE(ic))
7566     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7567   ic->generated = 1;
7568 }
7569
7570 /*-----------------------------------------------------------------*/
7571 /* jmpTrueOrFalse -                                                */
7572 /*-----------------------------------------------------------------*/
7573 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7574 {
7575   // ugly but optimized by peephole
7576   FENTRY;
7577   if(IC_TRUE(ic)){
7578     symbol *nlbl = newiTempLabel(NULL);
7579       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7580       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7581       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7582       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7583   } else {
7584     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7585     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7586   }
7587   ic->generated = 1;
7588 }
7589
7590 /*-----------------------------------------------------------------*/
7591 /* genAnd  - code for and                                          */
7592 /*-----------------------------------------------------------------*/
7593 static void genAnd (iCode *ic, iCode *ifx)
7594 {
7595   operand *left, *right, *result;
7596   int size, offset=0;  
7597   unsigned long lit = 0L;
7598   int bytelit = 0;
7599   resolvedIfx rIfx;
7600
7601     FENTRY;
7602     
7603   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7604   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7605   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7606
7607   resolveIfx(&rIfx,ifx);
7608
7609   /* if left is a literal & right is not then exchange them */
7610   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7611       AOP_NEEDSACC(left)) {
7612     operand *tmp = right ;
7613     right = left;
7614     left = tmp;
7615   }
7616
7617   /* if result = right then exchange them */
7618   if(pic16_sameRegs(AOP(result),AOP(right))){
7619     operand *tmp = right ;
7620     right = left;
7621     left = tmp;
7622   }
7623
7624   /* if right is bit then exchange them */
7625   if (AOP_TYPE(right) == AOP_CRY &&
7626       AOP_TYPE(left) != AOP_CRY){
7627     operand *tmp = right ;
7628     right = left;
7629     left = tmp;
7630   }
7631   if(AOP_TYPE(right) == AOP_LIT)
7632     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7633
7634   size = AOP_SIZE(result);
7635
7636   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7637
7638   // if(bit & yy)
7639   // result = bit & yy;
7640   if (AOP_TYPE(left) == AOP_CRY){
7641     // c = bit & literal;
7642     if(AOP_TYPE(right) == AOP_LIT){
7643       if(lit & 1) {
7644         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7645           // no change
7646           goto release;
7647         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7648       } else {
7649         // bit(result) = 0;
7650         if(size && (AOP_TYPE(result) == AOP_CRY)){
7651           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7652           goto release;
7653         }
7654         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7655           jumpIfTrue(ifx);
7656           goto release;
7657         }
7658         pic16_emitcode("clr","c");
7659       }
7660     } else {
7661       if (AOP_TYPE(right) == AOP_CRY){
7662         // c = bit & bit;
7663         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7664         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7665       } else {
7666         // c = bit & val;
7667         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7668         // c = lsb
7669         pic16_emitcode("rrc","a");
7670         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7671       }
7672     }
7673     // bit = c
7674     // val = c
7675     if(size)
7676       pic16_outBitC(result);
7677     // if(bit & ...)
7678     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7679       genIfxJump(ifx, "c");           
7680     goto release ;
7681   }
7682
7683   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7684   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7685   if((AOP_TYPE(right) == AOP_LIT) &&
7686      (AOP_TYPE(result) == AOP_CRY) &&
7687      (AOP_TYPE(left) != AOP_CRY)){
7688     int posbit = isLiteralBit(lit);
7689     /* left &  2^n */
7690     if(posbit){
7691       posbit--;
7692       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7693       // bit = left & 2^n
7694       if(size)
7695         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7696       // if(left &  2^n)
7697       else{
7698         if(ifx){
7699 /*
7700           if(IC_TRUE(ifx)) {
7701             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7702             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7703           } else {
7704             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7705             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7706           }
7707 */
7708         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7709         size = AOP_SIZE(left);
7710
7711         {
7712           int bp = posbit, ofs=0;
7713           
7714             while(bp > 7) {
7715               bp -= 8;
7716               ofs++;
7717             }
7718
7719           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7720                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7721
7722         }
7723 /*
7724           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7725                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7726 */
7727           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7728           
7729           ifx->generated = 1;
7730         }
7731         goto release;
7732       }
7733     } else {
7734       symbol *tlbl = newiTempLabel(NULL);
7735       int sizel = AOP_SIZE(left);
7736
7737       if(size)
7738         emitSETC;
7739
7740       while(sizel--) {
7741         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7742
7743           /* patch provided by Aaron Colwell */
7744           if((posbit = isLiteralBit(bytelit)) != 0) {
7745               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7746                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7747                                                 (posbit-1),0, PO_GPR_REGISTER));
7748
7749               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7750 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7751           } else {
7752               if (bytelit == 0xff) {
7753                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7754                    * a peephole could optimize it out -- VR */
7755                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7756               } else {
7757                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7758                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7759               }
7760
7761               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7762                             pic16_popGetLabel(tlbl->key));
7763           }
7764         
7765 #if 0
7766           /* old code, left here for reference -- VR 09/2004 */
7767           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7768           // byte ==  2^n ?
7769           if((posbit = isLiteralBit(bytelit)) != 0)
7770             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7771           else{
7772             if(bytelit != 0x0FFL)
7773               pic16_emitcode("anl","a,%s",
7774                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7775             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7776           }
7777 #endif
7778         }
7779         offset++;
7780       }
7781       // bit = left & literal
7782       if(size) {
7783         emitCLRC;
7784         pic16_emitpLabel(tlbl->key);
7785       }
7786       // if(left & literal)
7787       else {
7788         if(ifx) {
7789           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7790           ifx->generated = 1;
7791         }
7792         pic16_emitpLabel(tlbl->key);
7793         goto release;
7794       }
7795     }
7796
7797     pic16_outBitC(result);
7798     goto release ;
7799   }
7800
7801   /* if left is same as result */
7802   if(pic16_sameRegs(AOP(result),AOP(left))){
7803     int know_W = -1;
7804     for(;size--; offset++,lit>>=8) {
7805       if(AOP_TYPE(right) == AOP_LIT){
7806         switch(lit & 0xff) {
7807         case 0x00:
7808           /*  and'ing with 0 has clears the result */
7809 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7810           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7811           break;
7812         case 0xff:
7813           /* and'ing with 0xff is a nop when the result and left are the same */
7814           break;
7815
7816         default:
7817           {
7818             int p = pic16_my_powof2( (~lit) & 0xff );
7819             if(p>=0) {
7820               /* only one bit is set in the literal, so use a bcf instruction */
7821 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7822               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7823
7824             } else {
7825               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7826               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7827               if(know_W != (lit&0xff))
7828                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7829               know_W = lit &0xff;
7830               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7831             }
7832           }    
7833         }
7834       } else {
7835         if (AOP_TYPE(left) == AOP_ACC) {
7836           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7837         } else {                    
7838           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7839           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7840
7841         }
7842       }
7843     }
7844
7845   } else {
7846     // left & result in different registers
7847     if(AOP_TYPE(result) == AOP_CRY){
7848       // result = bit
7849       // if(size), result in bit
7850       // if(!size && ifx), conditional oper: if(left & right)
7851       symbol *tlbl = newiTempLabel(NULL);
7852       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7853       if(size)
7854         pic16_emitcode("setb","c");
7855       while(sizer--){
7856         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7857         pic16_emitcode("anl","a,%s",
7858                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7859         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7860         offset++;
7861       }
7862       if(size){
7863         CLRC;
7864         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7865         pic16_outBitC(result);
7866       } else if(ifx)
7867         jmpTrueOrFalse(ifx, tlbl);
7868     } else {
7869       for(;(size--);offset++) {
7870         // normal case
7871         // result = left & right
7872         if(AOP_TYPE(right) == AOP_LIT){
7873           int t = (lit >> (offset*8)) & 0x0FFL;
7874           switch(t) { 
7875           case 0x00:
7876             pic16_emitcode("clrf","%s",
7877                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7878             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7879             break;
7880           case 0xff:
7881             pic16_emitcode("movf","%s,w",
7882                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7883             pic16_emitcode("movwf","%s",
7884                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7885             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7886             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7887             break;
7888           default:
7889             pic16_emitcode("movlw","0x%x",t);
7890             pic16_emitcode("andwf","%s,w",
7891                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7892             pic16_emitcode("movwf","%s",
7893                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7894               
7895             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7896             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7897             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7898           }
7899           continue;
7900         }
7901
7902         if (AOP_TYPE(left) == AOP_ACC) {
7903           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7904           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7905         } else {
7906           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7907           pic16_emitcode("andwf","%s,w",
7908                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7909           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7910           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7911         }
7912         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7913         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7914       }
7915     }
7916   }
7917
7918   release :
7919     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7920   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7921   pic16_freeAsmop(result,NULL,ic,TRUE);     
7922 }
7923
7924 /*-----------------------------------------------------------------*/
7925 /* genOr  - code for or                                            */
7926 /*-----------------------------------------------------------------*/
7927 static void genOr (iCode *ic, iCode *ifx)
7928 {
7929     operand *left, *right, *result;
7930     int size, offset=0;
7931     unsigned long lit = 0L;
7932
7933     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7934     FENTRY;
7935
7936     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7937     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7938     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7939
7940     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7941
7942     /* if left is a literal & right is not then exchange them */
7943     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7944         AOP_NEEDSACC(left)) {
7945         operand *tmp = right ;
7946         right = left;
7947         left = tmp;
7948     }
7949
7950     /* if result = right then exchange them */
7951     if(pic16_sameRegs(AOP(result),AOP(right))){
7952         operand *tmp = right ;
7953         right = left;
7954         left = tmp;
7955     }
7956
7957     /* if right is bit then exchange them */
7958     if (AOP_TYPE(right) == AOP_CRY &&
7959         AOP_TYPE(left) != AOP_CRY){
7960         operand *tmp = right ;
7961         right = left;
7962         left = tmp;
7963     }
7964
7965     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7966
7967     if(AOP_TYPE(right) == AOP_LIT)
7968         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7969
7970     size = AOP_SIZE(result);
7971
7972     // if(bit | yy)
7973     // xx = bit | yy;
7974     if (AOP_TYPE(left) == AOP_CRY){
7975         if(AOP_TYPE(right) == AOP_LIT){
7976             // c = bit & literal;
7977             if(lit){
7978                 // lit != 0 => result = 1
7979                 if(AOP_TYPE(result) == AOP_CRY){
7980                   if(size)
7981                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7982                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7983                   //     AOP(result)->aopu.aop_dir,
7984                   //     AOP(result)->aopu.aop_dir);
7985                     else if(ifx)
7986                         continueIfTrue(ifx);
7987                     goto release;
7988                 }
7989             } else {
7990                 // lit == 0 => result = left
7991                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7992                     goto release;
7993                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7994             }
7995         } else {
7996             if (AOP_TYPE(right) == AOP_CRY){
7997               if(pic16_sameRegs(AOP(result),AOP(left))){
7998                 // c = bit | bit;
7999                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8000                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8001                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8002
8003                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8004                          AOP(result)->aopu.aop_dir,
8005                          AOP(result)->aopu.aop_dir);
8006                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8007                          AOP(right)->aopu.aop_dir,
8008                          AOP(right)->aopu.aop_dir);
8009                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8010                          AOP(result)->aopu.aop_dir,
8011                          AOP(result)->aopu.aop_dir);
8012               } else {
8013                 if( AOP_TYPE(result) == AOP_ACC) {
8014                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8015                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8016                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8017                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8018
8019                 } else {
8020
8021                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),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_BSF,   pic16_popGet(AOP(result),0));
8025
8026                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8027                                  AOP(result)->aopu.aop_dir,
8028                                  AOP(result)->aopu.aop_dir);
8029                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8030                                  AOP(right)->aopu.aop_dir,
8031                                  AOP(right)->aopu.aop_dir);
8032                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8033                                  AOP(left)->aopu.aop_dir,
8034                                  AOP(left)->aopu.aop_dir);
8035                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8036                                  AOP(result)->aopu.aop_dir,
8037                                  AOP(result)->aopu.aop_dir);
8038                 }
8039               }
8040             } else {
8041                 // c = bit | val;
8042                 symbol *tlbl = newiTempLabel(NULL);
8043                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8044
8045
8046                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8047                 if( AOP_TYPE(right) == AOP_ACC) {
8048                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8049                   emitSKPNZ;
8050                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8051                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8052                 }
8053
8054
8055
8056                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8057                     pic16_emitcode(";XXX setb","c");
8058                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8059                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8060                 pic16_toBoolean(right);
8061                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8062                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8063                     jmpTrueOrFalse(ifx, tlbl);
8064                     goto release;
8065                 } else {
8066                     CLRC;
8067                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8068                 }
8069             }
8070         }
8071         // bit = c
8072         // val = c
8073         if(size)
8074             pic16_outBitC(result);
8075         // if(bit | ...)
8076         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8077             genIfxJump(ifx, "c");           
8078         goto release ;
8079     }
8080
8081     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8082     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8083     if((AOP_TYPE(right) == AOP_LIT) &&
8084        (AOP_TYPE(result) == AOP_CRY) &&
8085        (AOP_TYPE(left) != AOP_CRY)){
8086         if(lit){
8087           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8088             // result = 1
8089             if(size)
8090                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8091             else 
8092                 continueIfTrue(ifx);
8093             goto release;
8094         } else {
8095           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8096             // lit = 0, result = boolean(left)
8097             if(size)
8098                 pic16_emitcode(";XXX setb","c");
8099             pic16_toBoolean(right);
8100             if(size){
8101                 symbol *tlbl = newiTempLabel(NULL);
8102                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8103                 CLRC;
8104                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8105             } else {
8106                 genIfxJump (ifx,"a");
8107                 goto release;
8108             }
8109         }
8110         pic16_outBitC(result);
8111         goto release ;
8112     }
8113
8114     /* if left is same as result */
8115     if(pic16_sameRegs(AOP(result),AOP(left))){
8116       int know_W = -1;
8117       for(;size--; offset++,lit>>=8) {
8118         if(AOP_TYPE(right) == AOP_LIT){
8119           if((lit & 0xff) == 0)
8120             /*  or'ing with 0 has no effect */
8121             continue;
8122           else {
8123             int p = pic16_my_powof2(lit & 0xff);
8124             if(p>=0) {
8125               /* only one bit is set in the literal, so use a bsf instruction */
8126               pic16_emitpcode(POC_BSF,
8127                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8128             } else {
8129               if(know_W != (lit & 0xff))
8130                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8131               know_W = lit & 0xff;
8132               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8133             }
8134                     
8135           }
8136         } else {
8137           if (AOP_TYPE(left) == AOP_ACC) {
8138             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8139 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8140           } else {                  
8141             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8142             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8143
8144 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8145 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8146
8147           }
8148         }
8149       }
8150     } else {
8151         // left & result in different registers
8152         if(AOP_TYPE(result) == AOP_CRY){
8153             // result = bit
8154             // if(size), result in bit
8155             // if(!size && ifx), conditional oper: if(left | right)
8156             symbol *tlbl = newiTempLabel(NULL);
8157             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8158             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8159
8160
8161             if(size)
8162                 pic16_emitcode(";XXX setb","c");
8163             while(sizer--){
8164                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8165                 pic16_emitcode(";XXX orl","a,%s",
8166                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8167                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8168                 offset++;
8169             }
8170             if(size){
8171                 CLRC;
8172                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8173                 pic16_outBitC(result);
8174             } else if(ifx)
8175                 jmpTrueOrFalse(ifx, tlbl);
8176         } else for(;(size--);offset++){
8177           // normal case
8178           // result = left & right
8179           if(AOP_TYPE(right) == AOP_LIT){
8180             int t = (lit >> (offset*8)) & 0x0FFL;
8181             switch(t) { 
8182             case 0x00:
8183               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8184               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8185
8186 //            pic16_emitcode("movf","%s,w",
8187 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8188 //            pic16_emitcode("movwf","%s",
8189 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8190               break;
8191             default:
8192               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8193               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8194               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8195
8196 //            pic16_emitcode("movlw","0x%x",t);
8197 //            pic16_emitcode("iorwf","%s,w",
8198 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8199 //            pic16_emitcode("movwf","%s",
8200 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8201               
8202             }
8203             continue;
8204           }
8205
8206           // faster than result <- left, anl result,right
8207           // and better if result is SFR
8208           if (AOP_TYPE(left) == AOP_ACC) {
8209             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8210 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8211           } else {
8212             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8213             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8214
8215 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8216 //          pic16_emitcode("iorwf","%s,w",
8217 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8218           }
8219           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8220 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8221         }
8222     }
8223
8224 release :
8225     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8226     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8227     pic16_freeAsmop(result,NULL,ic,TRUE);     
8228 }
8229
8230 /*-----------------------------------------------------------------*/
8231 /* genXor - code for xclusive or                                   */
8232 /*-----------------------------------------------------------------*/
8233 static void genXor (iCode *ic, iCode *ifx)
8234 {
8235   operand *left, *right, *result;
8236   int size, offset=0;
8237   unsigned long lit = 0L;
8238
8239   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8240   FENTRY;
8241
8242   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8243   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8244   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8245
8246   /* if left is a literal & right is not ||
8247      if left needs acc & right does not */
8248   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8249       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8250     operand *tmp = right ;
8251     right = left;
8252     left = tmp;
8253   }
8254
8255   /* if result = right then exchange them */
8256   if(pic16_sameRegs(AOP(result),AOP(right))){
8257     operand *tmp = right ;
8258     right = left;
8259     left = tmp;
8260   }
8261
8262   /* if right is bit then exchange them */
8263   if (AOP_TYPE(right) == AOP_CRY &&
8264       AOP_TYPE(left) != AOP_CRY){
8265     operand *tmp = right ;
8266     right = left;
8267     left = tmp;
8268   }
8269   if(AOP_TYPE(right) == AOP_LIT)
8270     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8271
8272   size = AOP_SIZE(result);
8273
8274   // if(bit ^ yy)
8275   // xx = bit ^ yy;
8276   if (AOP_TYPE(left) == AOP_CRY){
8277     if(AOP_TYPE(right) == AOP_LIT){
8278       // c = bit & literal;
8279       if(lit>>1){
8280         // lit>>1  != 0 => result = 1
8281         if(AOP_TYPE(result) == AOP_CRY){
8282           if(size)
8283             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8284             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8285           else if(ifx)
8286             continueIfTrue(ifx);
8287           goto release;
8288         }
8289         pic16_emitcode("setb","c");
8290       } else{
8291         // lit == (0 or 1)
8292         if(lit == 0){
8293           // lit == 0, result = left
8294           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8295             goto release;
8296           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8297         } else{
8298           // lit == 1, result = not(left)
8299           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8300             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8301             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8302             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8303             goto release;
8304           } else {
8305             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8306             pic16_emitcode("cpl","c");
8307           }
8308         }
8309       }
8310
8311     } else {
8312       // right != literal
8313       symbol *tlbl = newiTempLabel(NULL);
8314       if (AOP_TYPE(right) == AOP_CRY){
8315         // c = bit ^ bit;
8316         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8317       }
8318       else{
8319         int sizer = AOP_SIZE(right);
8320         // c = bit ^ val
8321         // if val>>1 != 0, result = 1
8322         pic16_emitcode("setb","c");
8323         while(sizer){
8324           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8325           if(sizer == 1)
8326             // test the msb of the lsb
8327             pic16_emitcode("anl","a,#0xfe");
8328           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8329           sizer--;
8330         }
8331         // val = (0,1)
8332         pic16_emitcode("rrc","a");
8333       }
8334       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8335       pic16_emitcode("cpl","c");
8336       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8337     }
8338     // bit = c
8339     // val = c
8340     if(size)
8341       pic16_outBitC(result);
8342     // if(bit | ...)
8343     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8344       genIfxJump(ifx, "c");           
8345     goto release ;
8346   }
8347
8348   if(pic16_sameRegs(AOP(result),AOP(left))){
8349     /* if left is same as result */
8350     for(;size--; offset++) {
8351       if(AOP_TYPE(right) == AOP_LIT){
8352         int t  = (lit >> (offset*8)) & 0x0FFL;
8353         if(t == 0x00L)
8354           continue;
8355         else
8356           if (IS_AOP_PREG(left)) {
8357             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8358             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8359             pic16_aopPut(AOP(result),"a",offset);
8360           } else {
8361             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8362             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8363             pic16_emitcode("xrl","%s,%s",
8364                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8365                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8366           }
8367       } else {
8368         if (AOP_TYPE(left) == AOP_ACC)
8369           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8370         else {
8371           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8372           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8373 /*
8374           if (IS_AOP_PREG(left)) {
8375             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8376             pic16_aopPut(AOP(result),"a",offset);
8377           } else
8378             pic16_emitcode("xrl","%s,a",
8379                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8380 */
8381         }
8382       }
8383     }
8384   } else {
8385     // left & result in different registers
8386     if(AOP_TYPE(result) == AOP_CRY){
8387       // result = bit
8388       // if(size), result in bit
8389       // if(!size && ifx), conditional oper: if(left ^ right)
8390       symbol *tlbl = newiTempLabel(NULL);
8391       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8392       if(size)
8393         pic16_emitcode("setb","c");
8394       while(sizer--){
8395         if((AOP_TYPE(right) == AOP_LIT) &&
8396            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8397           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8398         } else {
8399           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8400           pic16_emitcode("xrl","a,%s",
8401                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8402         }
8403         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8404         offset++;
8405       }
8406       if(size){
8407         CLRC;
8408         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8409         pic16_outBitC(result);
8410       } else if(ifx)
8411         jmpTrueOrFalse(ifx, tlbl);
8412     } else for(;(size--);offset++){
8413       // normal case
8414       // result = left & right
8415       if(AOP_TYPE(right) == AOP_LIT){
8416         int t = (lit >> (offset*8)) & 0x0FFL;
8417         switch(t) { 
8418         case 0x00:
8419           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8420           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8421           pic16_emitcode("movf","%s,w",
8422                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8423           pic16_emitcode("movwf","%s",
8424                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8425           break;
8426         case 0xff:
8427           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8428           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8429           pic16_emitcode("comf","%s,w",
8430                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8431           pic16_emitcode("movwf","%s",
8432                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8433           break;
8434         default:
8435           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8436           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8437           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8438           pic16_emitcode("movlw","0x%x",t);
8439           pic16_emitcode("xorwf","%s,w",
8440                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8441           pic16_emitcode("movwf","%s",
8442                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8443
8444         }
8445         continue;
8446       }
8447
8448       // faster than result <- left, anl result,right
8449       // and better if result is SFR
8450       if (AOP_TYPE(left) == AOP_ACC) {
8451         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8452         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8453       } else {
8454         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8455         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8456         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8457         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8458       }
8459       if ( AOP_TYPE(result) != AOP_ACC){
8460         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8461         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8462       }
8463     }
8464   }
8465
8466   release :
8467     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8468   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8469   pic16_freeAsmop(result,NULL,ic,TRUE);     
8470 }
8471
8472 /*-----------------------------------------------------------------*/
8473 /* genInline - write the inline code out                           */
8474 /*-----------------------------------------------------------------*/
8475 static void genInline (iCode *ic)
8476 {
8477   char *buffer, *bp, *bp1;
8478     
8479         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8480
8481         _G.inLine += (!options.asmpeep);
8482
8483         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8484         strcpy(buffer,IC_INLINE(ic));
8485         
8486         while((bp1=strstr(bp, "\\n"))) {
8487           *bp1++ = '\n';
8488           *bp1++ = ' ';
8489           bp = bp1;
8490         }
8491         bp = bp1 = buffer;
8492
8493 #if 0
8494   /* This is an experimental code for #pragma inline
8495      and is temporarily disabled for 2.5.0 release */
8496         if(asmInlineMap)
8497         {
8498           symbol *sym;
8499           char *s;
8500           char *cbuf;
8501           int cblen;
8502
8503             cbuf = Safe_strdup(buffer);
8504             cblen = strlen(buffer)+1;
8505             memset(cbuf, 0, cblen);
8506
8507             bp = buffer;
8508             bp1 = cbuf;
8509             while(*bp) {
8510               if(*bp != '%')*bp1++ = *bp++;
8511               else {
8512                 int i;
8513
8514                   bp++;
8515                   i = *bp - '0';
8516                   if(i>elementsInSet(asmInlineMap))break;
8517                   
8518                   bp++;
8519                   s = indexSet(asmInlineMap, i);
8520                   DEBUGpc("searching symbol s = `%s'", s);
8521                   sym = findSym(SymbolTab, NULL, s);
8522
8523                   if(sym->reqv) {
8524                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8525                   } else {
8526                     strcat(bp1, sym->rname);
8527                   }
8528                   
8529                   while(*bp1)bp1++;
8530               }
8531               
8532               if(strlen(bp1) > cblen - 16) {
8533                 int i = strlen(cbuf);
8534                 cblen += 50;
8535                 cbuf = realloc(cbuf, cblen);
8536                 memset(cbuf+i, 0, 50);
8537                 bp1 = cbuf + i;
8538               }
8539             }
8540             
8541             free(buffer);
8542             buffer = Safe_strdup( cbuf );
8543             free(cbuf);
8544             
8545             bp = bp1 = buffer;
8546         }
8547 #endif  /* 0 */
8548
8549         /* emit each line as a code */
8550         while (*bp) {
8551                 if (*bp == '\n') {
8552                         *bp++ = '\0';
8553
8554                         if(*bp1)
8555                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8556                         bp1 = bp;
8557                 } else {
8558                         if (*bp == ':') {
8559                                 bp++;
8560                                 *bp = '\0';
8561                                 bp++;
8562
8563                                 /* print label, use this special format with NULL directive
8564                                  * to denote that the argument should not be indented with tab */
8565                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8566                                 bp1 = bp;
8567                         } if (*bp == ';') {
8568                                 /* advance to end of line (prevent splitting of comments at ':' */
8569                                 while (*bp && *bp != '\n') {
8570                                         bp++;
8571                                 } // while
8572                         } else
8573                                 bp++;
8574                 }
8575         }
8576
8577         if ((bp1 != bp) && *bp1)
8578                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8579
8580
8581     Safe_free(buffer);
8582
8583     _G.inLine -= (!options.asmpeep);
8584 }
8585
8586 /*-----------------------------------------------------------------*/
8587 /* genRRC - rotate right with carry                                */
8588 /*-----------------------------------------------------------------*/
8589 static void genRRC (iCode *ic)
8590 {
8591   operand *left , *result ;
8592   int size, offset = 0, same;
8593
8594   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8595
8596   /* rotate right with carry */
8597   left = IC_LEFT(ic);
8598   result=IC_RESULT(ic);
8599   pic16_aopOp (left,ic,FALSE);
8600   pic16_aopOp (result,ic,TRUE);
8601
8602   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8603
8604   same = pic16_sameRegs(AOP(result),AOP(left));
8605
8606   size = AOP_SIZE(result);    
8607
8608   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8609
8610   /* get the lsb and put it into the carry */
8611   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8612
8613   offset = 0 ;
8614
8615   while(size--) {
8616
8617     if(same) {
8618       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8619     } else {
8620       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8621       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8622     }
8623
8624     offset++;
8625   }
8626
8627   pic16_freeAsmop(left,NULL,ic,TRUE);
8628   pic16_freeAsmop(result,NULL,ic,TRUE);
8629 }
8630
8631 /*-----------------------------------------------------------------*/
8632 /* genRLC - generate code for rotate left with carry               */
8633 /*-----------------------------------------------------------------*/
8634 static void genRLC (iCode *ic)
8635 {    
8636   operand *left , *result ;
8637   int size, offset = 0;
8638   int same;
8639
8640   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8641   /* rotate right with carry */
8642   left = IC_LEFT(ic);
8643   result=IC_RESULT(ic);
8644   pic16_aopOp (left,ic,FALSE);
8645   pic16_aopOp (result,ic,TRUE);
8646
8647   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8648
8649   same = pic16_sameRegs(AOP(result),AOP(left));
8650
8651   /* move it to the result */
8652   size = AOP_SIZE(result);    
8653
8654   /* get the msb and put it into the carry */
8655   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8656
8657   offset = 0 ;
8658
8659   while(size--) {
8660
8661     if(same) {
8662       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8663     } else {
8664       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8665       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8666     }
8667
8668     offset++;
8669   }
8670
8671
8672   pic16_freeAsmop(left,NULL,ic,TRUE);
8673   pic16_freeAsmop(result,NULL,ic,TRUE);
8674 }
8675
8676
8677 /* gpasm can get the highest order bit with HIGH/UPPER
8678  * so the following probably is not needed -- VR */
8679  
8680 /*-----------------------------------------------------------------*/
8681 /* genGetHbit - generates code get highest order bit               */
8682 /*-----------------------------------------------------------------*/
8683 static void genGetHbit (iCode *ic)
8684 {
8685     operand *left, *result;
8686     left = IC_LEFT(ic);
8687     result=IC_RESULT(ic);
8688     pic16_aopOp (left,ic,FALSE);
8689     pic16_aopOp (result,ic,FALSE);
8690
8691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8692     /* get the highest order byte into a */
8693     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8694     if(AOP_TYPE(result) == AOP_CRY){
8695         pic16_emitcode("rlc","a");
8696         pic16_outBitC(result);
8697     }
8698     else{
8699         pic16_emitcode("rl","a");
8700         pic16_emitcode("anl","a,#0x01");
8701         pic16_outAcc(result);
8702     }
8703
8704
8705     pic16_freeAsmop(left,NULL,ic,TRUE);
8706     pic16_freeAsmop(result,NULL,ic,TRUE);
8707 }
8708
8709 #if 0
8710 /*-----------------------------------------------------------------*/
8711 /* AccRol - rotate left accumulator by known count                 */
8712 /*-----------------------------------------------------------------*/
8713 static void AccRol (int shCount)
8714 {
8715     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8716     shCount &= 0x0007;              // shCount : 0..7
8717     switch(shCount){
8718         case 0 :
8719             break;
8720         case 1 :
8721             pic16_emitcode("rl","a");
8722             break;
8723         case 2 :
8724             pic16_emitcode("rl","a");
8725             pic16_emitcode("rl","a");
8726             break;
8727         case 3 :
8728             pic16_emitcode("swap","a");
8729             pic16_emitcode("rr","a");
8730             break;
8731         case 4 :
8732             pic16_emitcode("swap","a");
8733             break;
8734         case 5 :
8735             pic16_emitcode("swap","a");
8736             pic16_emitcode("rl","a");
8737             break;
8738         case 6 :
8739             pic16_emitcode("rr","a");
8740             pic16_emitcode("rr","a");
8741             break;
8742         case 7 :
8743             pic16_emitcode("rr","a");
8744             break;
8745     }
8746 }
8747 #endif
8748
8749 /*-----------------------------------------------------------------*/
8750 /* AccLsh - left shift accumulator by known count                  */
8751 /*-----------------------------------------------------------------*/
8752 static void AccLsh (int shCount, int doMask)
8753 {
8754         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8755         switch(shCount){
8756                 case 0 :
8757                         return;
8758                         break;
8759                 case 1 :
8760                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8761                         break;
8762                 case 2 :
8763                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8764                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8765                         break;
8766                 case 3 :
8767                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8768                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8769                         break;
8770                 case 4 :
8771                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8772                         break;
8773                 case 5 :
8774                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8775                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8776                         break;
8777                 case 6 :
8778                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8779                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8780                         break;
8781                 case 7 :
8782                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8783                         break;
8784         }
8785         if (doMask) {
8786                 /* no masking is required in genPackBits */
8787                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8788         }
8789 }
8790
8791 /*-----------------------------------------------------------------*/
8792 /* AccRsh - right shift accumulator by known count                 */
8793 /*-----------------------------------------------------------------*/
8794 static void AccRsh (int shCount, int andmask)
8795 {
8796         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8797         switch(shCount){
8798                 case 0 :
8799                         return; break;
8800                 case 1 :
8801                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8802                         break;
8803                 case 2 :
8804                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8805                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8806                         break;
8807                 case 3 :
8808                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8809                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8810                         break;
8811                 case 4 :
8812                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8813                         break;
8814                 case 5 :
8815                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8816                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8817                         break;
8818                 case 6 :
8819                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8820                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8821                         break;
8822                 case 7 :
8823                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8824                         break;
8825         }
8826         
8827         if(andmask)
8828                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8829         else
8830                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8831 }
8832
8833 #if 0
8834 /*-----------------------------------------------------------------*/
8835 /* AccSRsh - signed right shift accumulator by known count                 */
8836 /*-----------------------------------------------------------------*/
8837 static void AccSRsh (int shCount)
8838 {
8839     symbol *tlbl ;
8840     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8841     if(shCount != 0){
8842         if(shCount == 1){
8843             pic16_emitcode("mov","c,acc.7");
8844             pic16_emitcode("rrc","a");
8845         } else if(shCount == 2){
8846             pic16_emitcode("mov","c,acc.7");
8847             pic16_emitcode("rrc","a");
8848             pic16_emitcode("mov","c,acc.7");
8849             pic16_emitcode("rrc","a");
8850         } else {
8851             tlbl = newiTempLabel(NULL);
8852             /* rotate right accumulator */
8853             AccRol(8 - shCount);
8854             /* and kill the higher order bits */
8855             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8856             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8857             pic16_emitcode("orl","a,#0x%02x",
8858                      (unsigned char)~SRMask[shCount]);
8859             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8860         }
8861     }
8862 }
8863 #endif
8864
8865 /*-----------------------------------------------------------------*/
8866 /* shiftR1Left2Result - shift right one byte from left to result   */
8867 /*-----------------------------------------------------------------*/
8868 static void shiftR1Left2ResultSigned (operand *left, int offl,
8869                                 operand *result, int offr,
8870                                 int shCount)
8871 {
8872   int same;
8873
8874   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8875
8876   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8877
8878   switch(shCount) {
8879   case 1:
8880     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8881     if(same) 
8882       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8883     else {
8884       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8885       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8886     }
8887
8888     break;
8889   case 2:
8890
8891     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8892     if(same) 
8893       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8894     else {
8895       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8896       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8897     }
8898     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8899     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8900
8901     break;
8902
8903   case 3:
8904     if(same)
8905       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8906     else {
8907       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8908       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8909     }
8910
8911     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8912     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8913     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8914
8915     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8916     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8917
8918     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919     break;
8920
8921   case 4:
8922     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8923     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8924     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8925     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8926     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8927     break;
8928   case 5:
8929     if(same) {
8930       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8931     } else {
8932       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8933       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8934     }
8935     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8936     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8937     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8938     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8939     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8940     break;
8941
8942   case 6:
8943     if(same) {
8944       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8945       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8946       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8947       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8948       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8949       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8950     } else {
8951       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8952       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8953       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8954       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8955       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8956     }
8957     break;
8958
8959   case 7:
8960     if(same) {
8961       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8962       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8963       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8964       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8965     } else {
8966       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8968       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8969     }
8970
8971   default:
8972     break;
8973   }
8974 }
8975
8976 /*-----------------------------------------------------------------*/
8977 /* shiftR1Left2Result - shift right one byte from left to result   */
8978 /*-----------------------------------------------------------------*/
8979 static void shiftR1Left2Result (operand *left, int offl,
8980                                 operand *result, int offr,
8981                                 int shCount, int sign)
8982 {
8983   int same;
8984
8985   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8986
8987   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8988
8989   /* Copy the msb into the carry if signed. */
8990   if(sign) {
8991     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8992     return;
8993   }
8994
8995
8996
8997   switch(shCount) {
8998   case 1:
8999     emitCLRC;
9000     if(same) 
9001       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9002     else {
9003       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9004       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9005     }
9006     break;
9007   case 2:
9008     emitCLRC;
9009     if(same) {
9010       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9011     } else {
9012       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9013       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9014     }
9015     emitCLRC;
9016     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9017
9018     break;
9019   case 3:
9020     if(same)
9021       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9022     else {
9023       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9024       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9025     }
9026
9027     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9028     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9029     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9030     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9031     break;
9032       
9033   case 4:
9034     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9035     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9036     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9037     break;
9038
9039   case 5:
9040     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9041     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9042     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9043     //emitCLRC;
9044     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9045
9046     break;
9047   case 6:
9048
9049     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9050     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9051     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9052     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9053     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9054     break;
9055
9056   case 7:
9057
9058     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9059     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9060     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9061
9062     break;
9063
9064   default:
9065     break;
9066   }
9067 }
9068
9069 /*-----------------------------------------------------------------*/
9070 /* shiftL1Left2Result - shift left one byte from left to result    */
9071 /*-----------------------------------------------------------------*/
9072 static void shiftL1Left2Result (operand *left, int offl,
9073                                 operand *result, int offr, int shCount)
9074 {
9075   int same;
9076
9077   //    char *l;
9078   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9079
9080   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9081   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9082     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9083     //    MOVA(l);
9084     /* shift left accumulator */
9085     //AccLsh(shCount, 1); // don't comment out just yet...
9086   //    pic16_aopPut(AOP(result),"a",offr);
9087
9088   switch(shCount) {
9089   case 1:
9090     /* Shift left 1 bit position */
9091     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9092     if(same) {
9093       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9094     } else {
9095       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9096       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9097     }
9098     break;
9099   case 2:
9100     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9101     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9102     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9103     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9104     break;
9105   case 3:
9106     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9107     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9108     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9109     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9110     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9111     break;
9112   case 4:
9113     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9114     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9115     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9116     break;
9117   case 5:
9118     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9119     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9120     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9121     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9122     break;
9123   case 6:
9124     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9125     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9126     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9127     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9128     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9129     break;
9130   case 7:
9131     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9132     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9133     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9134     break;
9135
9136   default:
9137     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9138   }
9139
9140 }
9141
9142 /*-----------------------------------------------------------------*/
9143 /* movLeft2Result - move byte from left to result                  */
9144 /*-----------------------------------------------------------------*/
9145 static void movLeft2Result (operand *left, int offl,
9146                             operand *result, int offr)
9147 {
9148   char *l;
9149   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9150   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9151     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9152
9153     if (*l == '@' && (IS_AOP_PREG(result))) {
9154       pic16_emitcode("mov","a,%s",l);
9155       pic16_aopPut(AOP(result),"a",offr);
9156     } else {
9157       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9158       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9159     }
9160   }
9161 }
9162
9163 /*-----------------------------------------------------------------*/
9164 /* shiftL2Left2Result - shift left two bytes from left to result   */
9165 /*-----------------------------------------------------------------*/
9166 static void shiftL2Left2Result (operand *left, int offl,
9167                                 operand *result, int offr, int shCount)
9168 {
9169   int same = pic16_sameRegs(AOP(result), AOP(left));
9170   int i;
9171
9172   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9173
9174   if (same && (offl != offr)) { // shift bytes
9175     if (offr > offl) {
9176        for(i=1;i>-1;i--) {
9177          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9178          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9179        }
9180     } else { // just treat as different later on
9181                 same = 0;
9182     }
9183   }
9184
9185   if(same) {
9186     switch(shCount) {
9187     case 0:
9188       break;
9189     case 1:
9190     case 2:
9191     case 3:
9192
9193       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9194       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9195       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9196
9197       while(--shCount) {
9198                 emitCLRC;
9199                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9200                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9201       }
9202
9203       break;
9204     case 4:
9205     case 5:
9206       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9207       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9208       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9209       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9210       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9211       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9212       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9213       if(shCount >=5) {
9214                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9215                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9216       }
9217       break;
9218     case 6:
9219       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9220       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9221       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9222       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9223       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9224       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9225       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9226       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9227       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9228       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9229       break;
9230     case 7:
9231       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9232       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9233       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9234       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9235       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9236     }
9237
9238   } else {
9239     switch(shCount) {
9240     case 0:
9241       break;
9242     case 1:
9243     case 2:
9244     case 3:
9245       /* note, use a mov/add for the shift since the mov has a
9246          chance of getting optimized out */
9247       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9248       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9249       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9250       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9251       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9252
9253       while(--shCount) {
9254                 emitCLRC;
9255                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9256                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9257       }
9258       break;
9259
9260     case 4:
9261     case 5:
9262       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9263       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9264       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9265       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9266       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9267       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9268       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9269       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9270
9271
9272       if(shCount == 5) {
9273                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9274                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9275       }
9276       break;
9277     case 6:
9278       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9279       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9280       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9281       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9282
9283       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9284       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9285       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9286       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9287       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9288       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9289       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9290       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9291       break;
9292     case 7:
9293       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9294       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9295       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9296       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9297       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9298     }
9299   }
9300
9301 }
9302 /*-----------------------------------------------------------------*/
9303 /* shiftR2Left2Result - shift right two bytes from left to result  */
9304 /*-----------------------------------------------------------------*/
9305 static void shiftR2Left2Result (operand *left, int offl,
9306                                 operand *result, int offr,
9307                                 int shCount, int sign)
9308 {
9309   int same = pic16_sameRegs(AOP(result), AOP(left));
9310   int i;
9311   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9312
9313   if (same && (offl != offr)) { // shift right bytes
9314     if (offr < offl) {
9315        for(i=0;i<2;i++) {
9316          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9317          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9318        }
9319     } else { // just treat as different later on
9320                 same = 0;
9321     }
9322   }
9323
9324   switch(shCount) {
9325   case 0:
9326     break;
9327   case 1:
9328   case 2:
9329   case 3:
9330     /* obtain sign from left operand */
9331     if(sign)
9332       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9333     else
9334       emitCLRC;
9335
9336     if(same) {
9337       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9338       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9339     } else {
9340       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9341       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9342       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9343       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9344     }
9345
9346     while(--shCount) {
9347       if(sign)
9348         /* now get sign from already assigned result (avoid BANKSEL) */
9349         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9350       else
9351         emitCLRC;
9352       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9353       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9354     }
9355     break;
9356   case 4:
9357   case 5:
9358     if(same) {
9359
9360       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9361       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9362       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9363
9364       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9365       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9366       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9367       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9368     } else {
9369       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9370       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9371       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9372
9373       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9374       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9375       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9376       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9377       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9378     }
9379
9380     if(shCount >=5) {
9381       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9382       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9383     }
9384
9385     if(sign) {
9386       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9387       pic16_emitpcode(POC_BTFSC, 
9388                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9389       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9390     }
9391
9392     break;
9393
9394   case 6:
9395     if(same) {
9396
9397       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9398       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9399
9400       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9401       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9402       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9403       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9404       if(sign) {
9405         pic16_emitpcode(POC_BTFSC, 
9406                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9407         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9408       }
9409       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9410       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9411       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9412       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9413     } else {
9414       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9415       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9416       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9417       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9418       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9419       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9420       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9421       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9422       if(sign) {
9423         pic16_emitpcode(POC_BTFSC, 
9424                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9425         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9426       }
9427       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9428       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9429
9430         
9431     }
9432
9433     break;
9434   case 7:
9435     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9436     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9437     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9438     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9439     if(sign) {
9440       emitSKPNC;
9441       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9442     } else 
9443       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9444   }
9445 }
9446
9447
9448 /*-----------------------------------------------------------------*/
9449 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9450 /*-----------------------------------------------------------------*/
9451 static void shiftLLeftOrResult (operand *left, int offl,
9452                                 operand *result, int offr, int shCount)
9453 {
9454     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9455
9456     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9457     /* shift left accumulator */
9458     AccLsh(shCount, 1);
9459     /* or with result */
9460     /* back to result */
9461     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9462 }
9463
9464 /*-----------------------------------------------------------------*/
9465 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9466 /*-----------------------------------------------------------------*/
9467 static void shiftRLeftOrResult (operand *left, int offl,
9468                                 operand *result, int offr, int shCount)
9469 {
9470     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9471     
9472     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9473     /* shift right accumulator */
9474     AccRsh(shCount, 1);
9475     /* or with result */
9476     /* back to result */
9477     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9478 }
9479
9480 /*-----------------------------------------------------------------*/
9481 /* genlshOne - left shift a one byte quantity by known count       */
9482 /*-----------------------------------------------------------------*/
9483 static void genlshOne (operand *result, operand *left, int shCount)
9484 {       
9485     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9486     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9487 }
9488
9489 /*-----------------------------------------------------------------*/
9490 /* genlshTwo - left shift two bytes by known amount != 0           */
9491 /*-----------------------------------------------------------------*/
9492 static void genlshTwo (operand *result,operand *left, int shCount)
9493 {
9494     int size;
9495     
9496     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9497     size = pic16_getDataSize(result);
9498
9499     /* if shCount >= 8 */
9500     if (shCount >= 8) {
9501         shCount -= 8 ;
9502
9503         if (size > 1){
9504             if (shCount)
9505                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9506             else 
9507                 movLeft2Result(left, LSB, result, MSB16);
9508         }
9509         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9510     }
9511
9512     /*  1 <= shCount <= 7 */
9513     else {  
9514         if(size == 1)
9515             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9516         else 
9517             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9518     }
9519 }
9520
9521 /*-----------------------------------------------------------------*/
9522 /* shiftLLong - shift left one long from left to result            */
9523 /* offr = LSB or MSB16                                             */
9524 /*-----------------------------------------------------------------*/
9525 static void shiftLLong (operand *left, operand *result, int offr )
9526 {
9527     int size = AOP_SIZE(result);
9528     int same = pic16_sameRegs(AOP(left),AOP(result));
9529         int i;
9530
9531     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9532
9533         if (same && (offr == MSB16)) { //shift one byte
9534                 for(i=size-1;i>=MSB16;i--) {
9535                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9536                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9537                 }
9538         } else {
9539                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9540         }
9541         
9542     if (size > LSB+offr ){
9543                 if (same) {
9544                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9545                 } else {
9546                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9547                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9548                 }
9549          }
9550
9551     if(size > MSB16+offr){
9552                 if (same) {
9553                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9554                 } else {
9555                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9556                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9557                 }
9558     }
9559
9560     if(size > MSB24+offr){
9561                 if (same) {
9562                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9563                 } else {
9564                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9565                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9566                 }
9567     }
9568
9569     if(size > MSB32+offr){
9570                 if (same) {
9571                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9572                 } else {
9573                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9574                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9575                 }
9576     }
9577     if(offr != LSB)
9578                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9579
9580 }
9581
9582 /*-----------------------------------------------------------------*/
9583 /* genlshFour - shift four byte by a known amount != 0             */
9584 /*-----------------------------------------------------------------*/
9585 static void genlshFour (operand *result, operand *left, int shCount)
9586 {
9587     int size;
9588
9589     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9590     size = AOP_SIZE(result);
9591
9592     /* if shifting more that 3 bytes */
9593     if (shCount >= 24 ) {
9594         shCount -= 24;
9595         if (shCount)
9596             /* lowest order of left goes to the highest
9597             order of the destination */
9598             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9599         else
9600             movLeft2Result(left, LSB, result, MSB32);
9601
9602                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9603                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9604                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9605
9606         return;
9607     }
9608
9609     /* more than two bytes */
9610     else if ( shCount >= 16 ) {
9611         /* lower order two bytes goes to higher order two bytes */
9612         shCount -= 16;
9613         /* if some more remaining */
9614         if (shCount)
9615             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9616         else {
9617             movLeft2Result(left, MSB16, result, MSB32);
9618             movLeft2Result(left, LSB, result, MSB24);
9619         }
9620                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9621                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9622         return;
9623     }    
9624
9625     /* if more than 1 byte */
9626     else if ( shCount >= 8 ) {
9627         /* lower order three bytes goes to higher order  three bytes */
9628         shCount -= 8;
9629         if(size == 2){
9630             if(shCount)
9631                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9632             else
9633                 movLeft2Result(left, LSB, result, MSB16);
9634         }
9635         else{   /* size = 4 */
9636             if(shCount == 0){
9637                 movLeft2Result(left, MSB24, result, MSB32);
9638                 movLeft2Result(left, MSB16, result, MSB24);
9639                 movLeft2Result(left, LSB, result, MSB16);
9640                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9641             }
9642             else if(shCount == 1)
9643                 shiftLLong(left, result, MSB16);
9644             else{
9645                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9646                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9647                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9648                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9649             }
9650         }
9651     }
9652
9653     /* 1 <= shCount <= 7 */
9654     else if(shCount <= 3)
9655     { 
9656         shiftLLong(left, result, LSB);
9657         while(--shCount >= 1)
9658             shiftLLong(result, result, LSB);
9659     }
9660     /* 3 <= shCount <= 7, optimize */
9661     else{
9662         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9663         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9664         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9665     }
9666 }
9667
9668 /*-----------------------------------------------------------------*/
9669 /* genLeftShiftLiteral - left shifting by known count              */
9670 /*-----------------------------------------------------------------*/
9671 void pic16_genLeftShiftLiteral (operand *left,
9672                                  operand *right,
9673                                  operand *result,
9674                                  iCode *ic)
9675 {    
9676     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9677     int size;
9678
9679     FENTRY;
9680     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9681     pic16_freeAsmop(right,NULL,ic,TRUE);
9682
9683     pic16_aopOp(left,ic,FALSE);
9684     pic16_aopOp(result,ic,TRUE);
9685
9686     size = getSize(operandType(result));
9687
9688 #if VIEW_SIZE
9689     pic16_emitcode("; shift left ","result %d, left %d",size,
9690              AOP_SIZE(left));
9691 #endif
9692
9693     /* I suppose that the left size >= result size */
9694     if(shCount == 0){
9695         while(size--){
9696             movLeft2Result(left, size, result, size);
9697         }
9698     }
9699
9700     else if(shCount >= (size * 8))
9701         while(size--)
9702             pic16_aopPut(AOP(result),zero,size);
9703     else{
9704         switch (size) {
9705             case 1:
9706                 genlshOne (result,left,shCount);
9707                 break;
9708
9709             case 2:
9710             case 3:
9711                 genlshTwo (result,left,shCount);
9712                 break;
9713
9714             case 4:
9715                 genlshFour (result,left,shCount);
9716                 break;
9717         }
9718     }
9719     pic16_freeAsmop(left,NULL,ic,TRUE);
9720     pic16_freeAsmop(result,NULL,ic,TRUE);
9721 }
9722
9723 /*-----------------------------------------------------------------*
9724  * genMultiAsm - repeat assembly instruction for size of register.
9725  * if endian == 1, then the high byte (i.e base address + size of 
9726  * register) is used first else the low byte is used first;
9727  *-----------------------------------------------------------------*/
9728 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9729 {
9730
9731   int offset = 0;
9732
9733   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9734
9735   if(!reg)
9736     return;
9737
9738   if(!endian) {
9739     endian = 1;
9740   } else {
9741     endian = -1;
9742     offset = size-1;
9743   }
9744
9745   while(size--) {
9746     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9747     offset += endian;
9748   }
9749
9750 }
9751
9752 #if !(USE_GENERIC_SIGNED_SHIFT)
9753 /*-----------------------------------------------------------------*/
9754 /* genLeftShift - generates code for left shifting                 */
9755 /*-----------------------------------------------------------------*/
9756 static void genLeftShift (iCode *ic)
9757 {
9758   operand *left,*right, *result;
9759   int size, offset;
9760 //  char *l;
9761   symbol *tlbl , *tlbl1;
9762   pCodeOp *pctemp;
9763
9764   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9765
9766   right = IC_RIGHT(ic);
9767   left  = IC_LEFT(ic);
9768   result = IC_RESULT(ic);
9769
9770   pic16_aopOp(right,ic,FALSE);
9771
9772   /* if the shift count is known then do it 
9773      as efficiently as possible */
9774   if (AOP_TYPE(right) == AOP_LIT) {
9775     pic16_genLeftShiftLiteral (left,right,result,ic);
9776     return ;
9777   }
9778
9779   /* shift count is unknown then we have to form
9780    * a loop. Get the loop count in WREG : Note: we take
9781    * only the lower order byte since shifting
9782    * more than 32 bits make no sense anyway, ( the
9783    * largest size of an object can be only 32 bits ) */
9784   
9785   pic16_aopOp(left,ic,FALSE);
9786   pic16_aopOp(result,ic,FALSE);
9787
9788   /* now move the left to the result if they are not the
9789    * same, and if size > 1,
9790    * and if right is not same to result (!!!) -- VR */
9791   if (!pic16_sameRegs(AOP(left),AOP(result))
9792       && (AOP_SIZE(result) > 1)) {
9793
9794     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9795
9796     size = AOP_SIZE(result);
9797     offset=0;
9798     while (size--) {
9799
9800 #if 0
9801       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9802       if (*l == '@' && (IS_AOP_PREG(result))) {
9803
9804           pic16_emitcode("mov","a,%s",l);
9805           pic16_aopPut(AOP(result),"a",offset);
9806       } else
9807 #endif
9808       {
9809         /* we don't know if left is a literal or a register, take care -- VR */
9810         pic16_mov2f(AOP(result), AOP(left), offset);
9811       }
9812       offset++;
9813     }
9814   }
9815
9816   size = AOP_SIZE(result);
9817
9818   /* if it is only one byte then */
9819   if (size == 1) {
9820     if(optimized_for_speed) {
9821       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9822       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9823       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9824       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9825       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9826       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9827       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9828       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9829       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9830       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9831       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9832       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9833     } else {
9834
9835       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9836
9837       tlbl = newiTempLabel(NULL);
9838
9839 #if 1
9840       /* this is already done, why change it? */
9841       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9842                 pic16_mov2f(AOP(result), AOP(left), 0);
9843       }
9844 #endif
9845
9846       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9847       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9848       pic16_emitpLabel(tlbl->key);
9849       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9850       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9851       emitSKPC;
9852       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9853     }
9854     goto release ;
9855   }
9856     
9857   if (pic16_sameRegs(AOP(left),AOP(result))) {
9858
9859     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9860     
9861     tlbl = newiTempLabel(NULL);
9862     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9863     genMultiAsm(POC_RRCF, result, size,1);
9864     pic16_emitpLabel(tlbl->key);
9865     genMultiAsm(POC_RLCF, result, size,0);
9866     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9867     emitSKPC;
9868     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9869     goto release;
9870   }
9871
9872   //tlbl = newiTempLabel(NULL);
9873   //offset = 0 ;   
9874   //tlbl1 = newiTempLabel(NULL);
9875
9876   //reAdjustPreg(AOP(result));    
9877     
9878   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9879   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9880   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9881   //MOVA(l);
9882   //pic16_emitcode("add","a,acc");         
9883   //pic16_aopPut(AOP(result),"a",offset++);
9884   //while (--size) {
9885   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9886   //  MOVA(l);
9887   //  pic16_emitcode("rlc","a");         
9888   //  pic16_aopPut(AOP(result),"a",offset++);
9889   //}
9890   //reAdjustPreg(AOP(result));
9891
9892   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9893   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9894
9895
9896   tlbl = newiTempLabel(NULL);
9897   tlbl1= newiTempLabel(NULL);
9898
9899   size = AOP_SIZE(result);
9900   offset = 1;
9901
9902   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9903
9904   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9905
9906   /* offset should be 0, 1 or 3 */
9907   
9908   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9909   emitSKPNZ;
9910   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9911
9912   pic16_emitpcode(POC_MOVWF, pctemp);
9913
9914
9915   pic16_emitpLabel(tlbl->key);
9916
9917   emitCLRC;
9918   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9919   while(--size)
9920     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9921
9922   pic16_emitpcode(POC_DECFSZ,  pctemp);
9923   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9924   pic16_emitpLabel(tlbl1->key);
9925
9926   pic16_popReleaseTempReg(pctemp,1);
9927
9928
9929  release:
9930   pic16_freeAsmop (right,NULL,ic,TRUE);
9931   pic16_freeAsmop(left,NULL,ic,TRUE);
9932   pic16_freeAsmop(result,NULL,ic,TRUE);
9933 }
9934 #endif
9935
9936
9937 #if 0
9938 #error old code (left here for reference)
9939 /*-----------------------------------------------------------------*/
9940 /* genLeftShift - generates code for left shifting                 */
9941 /*-----------------------------------------------------------------*/
9942 static void genLeftShift (iCode *ic)
9943 {
9944   operand *left,*right, *result;
9945   int size, offset;
9946   char *l;
9947   symbol *tlbl , *tlbl1;
9948   pCodeOp *pctemp;
9949
9950   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9951
9952   right = IC_RIGHT(ic);
9953   left  = IC_LEFT(ic);
9954   result = IC_RESULT(ic);
9955
9956   pic16_aopOp(right,ic,FALSE);
9957
9958   /* if the shift count is known then do it 
9959      as efficiently as possible */
9960   if (AOP_TYPE(right) == AOP_LIT) {
9961     pic16_genLeftShiftLiteral (left,right,result,ic);
9962     return ;
9963   }
9964
9965   /* shift count is unknown then we have to form 
9966      a loop get the loop count in B : Note: we take
9967      only the lower order byte since shifting
9968      more that 32 bits make no sense anyway, ( the
9969      largest size of an object can be only 32 bits ) */  
9970
9971     
9972   pic16_aopOp(left,ic,FALSE);
9973   pic16_aopOp(result,ic,FALSE);
9974
9975   /* now move the left to the result if they are not the
9976      same */
9977   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9978       AOP_SIZE(result) > 1) {
9979
9980     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9981
9982     size = AOP_SIZE(result);
9983     offset=0;
9984     while (size--) {
9985       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9986       if (*l == '@' && (IS_AOP_PREG(result))) {
9987
9988         pic16_emitcode("mov","a,%s",l);
9989         pic16_aopPut(AOP(result),"a",offset);
9990       } else {
9991
9992         /* we don't know if left is a literal or a register, take care -- VR */
9993         pic16_mov2f(AOP(result), AOP(left), offset);
9994       }
9995       offset++;
9996     }
9997   }
9998
9999   size = AOP_SIZE(result);
10000
10001   /* if it is only one byte then */
10002   if (size == 1) {
10003     if(optimized_for_speed) {
10004       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10005       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10006       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10007       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10008       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10009       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10010       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10011       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10012       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10013       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10014       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10015       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10016     } else {
10017
10018       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10019
10020       tlbl = newiTempLabel(NULL);
10021       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10022                 pic16_mov2f(AOP(result), AOP(left), 0);
10023                 
10024 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10025 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10026       }
10027
10028       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10029       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10030       pic16_emitpLabel(tlbl->key);
10031       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10032       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10033       emitSKPC;
10034       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10035     }
10036     goto release ;
10037   }
10038     
10039   if (pic16_sameRegs(AOP(left),AOP(result))) {
10040
10041     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10042     
10043     tlbl = newiTempLabel(NULL);
10044     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10045     genMultiAsm(POC_RRCF, result, size,1);
10046     pic16_emitpLabel(tlbl->key);
10047     genMultiAsm(POC_RLCF, result, size,0);
10048     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10049     emitSKPC;
10050     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10051     goto release;
10052   }
10053
10054   //tlbl = newiTempLabel(NULL);
10055   //offset = 0 ;   
10056   //tlbl1 = newiTempLabel(NULL);
10057
10058   //reAdjustPreg(AOP(result));    
10059     
10060   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10061   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10062   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10063   //MOVA(l);
10064   //pic16_emitcode("add","a,acc");         
10065   //pic16_aopPut(AOP(result),"a",offset++);
10066   //while (--size) {
10067   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10068   //  MOVA(l);
10069   //  pic16_emitcode("rlc","a");         
10070   //  pic16_aopPut(AOP(result),"a",offset++);
10071   //}
10072   //reAdjustPreg(AOP(result));
10073
10074   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10075   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10076
10077
10078   tlbl = newiTempLabel(NULL);
10079   tlbl1= newiTempLabel(NULL);
10080
10081   size = AOP_SIZE(result);
10082   offset = 1;
10083
10084   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10085
10086   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10087
10088   /* offset should be 0, 1 or 3 */
10089   
10090   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10091   emitSKPNZ;
10092   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10093
10094   pic16_emitpcode(POC_MOVWF, pctemp);
10095
10096
10097   pic16_emitpLabel(tlbl->key);
10098
10099   emitCLRC;
10100   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10101   while(--size)
10102     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10103
10104   pic16_emitpcode(POC_DECFSZ,  pctemp);
10105   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10106   pic16_emitpLabel(tlbl1->key);
10107
10108   pic16_popReleaseTempReg(pctemp,1);
10109
10110
10111  release:
10112   pic16_freeAsmop (right,NULL,ic,TRUE);
10113   pic16_freeAsmop(left,NULL,ic,TRUE);
10114   pic16_freeAsmop(result,NULL,ic,TRUE);
10115 }
10116 #endif
10117
10118 /*-----------------------------------------------------------------*/
10119 /* genrshOne - right shift a one byte quantity by known count      */
10120 /*-----------------------------------------------------------------*/
10121 static void genrshOne (operand *result, operand *left,
10122                        int shCount, int sign)
10123 {
10124     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10125     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10126 }
10127
10128 /*-----------------------------------------------------------------*/
10129 /* genrshTwo - right shift two bytes by known amount != 0          */
10130 /*-----------------------------------------------------------------*/
10131 static void genrshTwo (operand *result,operand *left,
10132                        int shCount, int sign)
10133 {
10134   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10135   /* if shCount >= 8 */
10136   if (shCount >= 8) {
10137     shCount -= 8 ;
10138     if (shCount)
10139       shiftR1Left2Result(left, MSB16, result, LSB,
10140                          shCount, sign);
10141     else
10142       movLeft2Result(left, MSB16, result, LSB);
10143
10144     pic16_addSign (result, 1, sign);
10145   }
10146
10147   /*  1 <= shCount <= 7 */
10148   else
10149     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10150 }
10151
10152 /*-----------------------------------------------------------------*/
10153 /* shiftRLong - shift right one long from left to result           */
10154 /* offl = LSB or MSB16                                             */
10155 /*-----------------------------------------------------------------*/
10156 static void shiftRLong (operand *left, int offl,
10157                         operand *result, int sign)
10158 {
10159     int size = AOP_SIZE(result);
10160     int same = pic16_sameRegs(AOP(left),AOP(result));
10161     int i;
10162     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10163
10164         if (same && (offl == MSB16)) { //shift one byte right
10165                 for(i=MSB16;i<size;i++) {
10166                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10167                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10168                 }
10169         }
10170
10171     if(sign)
10172                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10173         else
10174                 emitCLRC;
10175
10176         if (same) {
10177                 if (offl == LSB)
10178                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10179         } else {
10180         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10181         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10182         }
10183
10184     if(offl == MSB16) {
10185         /* add sign of "a" */
10186         pic16_addSign(result, MSB32, sign);
10187         }
10188
10189         if (same) {
10190         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10191         } else {
10192         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10193         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10194         }
10195         
10196         if (same) {
10197         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10198         } else {
10199         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10200         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10201         }
10202
10203         if (same) {
10204         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10205         } else {
10206         if(offl == LSB){
10207                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10208                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10209         }
10210         }
10211 }
10212
10213 /*-----------------------------------------------------------------*/
10214 /* genrshFour - shift four byte by a known amount != 0             */
10215 /*-----------------------------------------------------------------*/
10216 static void genrshFour (operand *result, operand *left,
10217                         int shCount, int sign)
10218 {
10219   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10220   /* if shifting more that 3 bytes */
10221   if(shCount >= 24 ) {
10222     shCount -= 24;
10223     if(shCount)
10224       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10225     else
10226       movLeft2Result(left, MSB32, result, LSB);
10227
10228     pic16_addSign(result, MSB16, sign);
10229   }
10230   else if(shCount >= 16){
10231     shCount -= 16;
10232     if(shCount)
10233       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10234     else{
10235       movLeft2Result(left, MSB24, result, LSB);
10236       movLeft2Result(left, MSB32, result, MSB16);
10237     }
10238     pic16_addSign(result, MSB24, sign);
10239   }
10240   else if(shCount >= 8){
10241     shCount -= 8;
10242     if(shCount == 1)
10243       shiftRLong(left, MSB16, result, sign);
10244     else if(shCount == 0){
10245       movLeft2Result(left, MSB16, result, LSB);
10246       movLeft2Result(left, MSB24, result, MSB16);
10247       movLeft2Result(left, MSB32, result, MSB24);
10248       pic16_addSign(result, MSB32, sign);
10249     }
10250     else{ //shcount >= 2
10251       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10252       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10253       /* the last shift is signed */
10254       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10255       pic16_addSign(result, MSB32, sign);
10256     }
10257   }
10258   else{   /* 1 <= shCount <= 7 */
10259     if(shCount <= 2){
10260       shiftRLong(left, LSB, result, sign);
10261       if(shCount == 2)
10262         shiftRLong(result, LSB, result, sign);
10263     }
10264     else{
10265       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10266       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10267       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10268     }
10269   }
10270 }
10271
10272 /*-----------------------------------------------------------------*/
10273 /* genRightShiftLiteral - right shifting by known count            */
10274 /*-----------------------------------------------------------------*/
10275 static void genRightShiftLiteral (operand *left,
10276                                   operand *right,
10277                                   operand *result,
10278                                   iCode *ic,
10279                                   int sign)
10280 {    
10281   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10282   int lsize,res_size;
10283
10284   pic16_freeAsmop(right,NULL,ic,TRUE);
10285
10286   pic16_aopOp(left,ic,FALSE);
10287   pic16_aopOp(result,ic,TRUE);
10288
10289   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10290
10291 #if VIEW_SIZE
10292   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10293                  AOP_SIZE(left));
10294 #endif
10295
10296   lsize = pic16_getDataSize(left);
10297   res_size = pic16_getDataSize(result);
10298   /* test the LEFT size !!! */
10299
10300   /* I suppose that the left size >= result size */
10301   if(shCount == 0){
10302     assert (res_size <= lsize);
10303     while (res_size--) {
10304       pic16_mov2f (AOP(result), AOP(left), res_size);
10305     } // for
10306   }
10307
10308   else if(shCount >= (lsize * 8)){
10309
10310     if(res_size == 1) {
10311       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10312       if(sign) {
10313         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10314         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10315       }
10316     } else {
10317
10318       if(sign) {
10319         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10320         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10321         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10322         while(res_size--)
10323           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10324
10325       } else {
10326
10327         while(res_size--)
10328           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10329       }
10330     }
10331   } else {
10332
10333     switch (res_size) {
10334     case 1:
10335       genrshOne (result,left,shCount,sign);
10336       break;
10337
10338     case 2:
10339       genrshTwo (result,left,shCount,sign);
10340       break;
10341
10342     case 4:
10343       genrshFour (result,left,shCount,sign);
10344       break;
10345     default :
10346       break;
10347     }
10348
10349   }
10350
10351   pic16_freeAsmop(left,NULL,ic,TRUE);
10352   pic16_freeAsmop(result,NULL,ic,TRUE);
10353 }
10354
10355 #if !(USE_GENERIC_SIGNED_SHIFT)
10356 /*-----------------------------------------------------------------*/
10357 /* genSignedRightShift - right shift of signed number              */
10358 /*-----------------------------------------------------------------*/
10359 static void genSignedRightShift (iCode *ic)
10360 {
10361   operand *right, *left, *result;
10362   int size, offset;
10363   //  char *l;
10364   symbol *tlbl, *tlbl1 ;
10365   pCodeOp *pctemp;
10366
10367   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10368
10369   /* we do it the hard way put the shift count in b
10370      and loop thru preserving the sign */
10371   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10372
10373   right = IC_RIGHT(ic);
10374   left  = IC_LEFT(ic);
10375   result = IC_RESULT(ic);
10376
10377   pic16_aopOp(right,ic,FALSE);  
10378   pic16_aopOp(left,ic,FALSE);
10379   pic16_aopOp(result,ic,FALSE);
10380
10381
10382   if ( AOP_TYPE(right) == AOP_LIT) {
10383     genRightShiftLiteral (left,right,result,ic,1);
10384     return ;
10385   }
10386   /* shift count is unknown then we have to form 
10387      a loop get the loop count in B : Note: we take
10388      only the lower order byte since shifting
10389      more that 32 bits make no sense anyway, ( the
10390      largest size of an object can be only 32 bits ) */  
10391
10392   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10393   //pic16_emitcode("inc","b");
10394   //pic16_freeAsmop (right,NULL,ic,TRUE);
10395   //pic16_aopOp(left,ic,FALSE);
10396   //pic16_aopOp(result,ic,FALSE);
10397
10398   /* now move the left to the result if they are not the
10399      same */
10400   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10401       AOP_SIZE(result) > 1) {
10402
10403     size = AOP_SIZE(result);
10404     offset=0;
10405     while (size--) { 
10406       /*
10407         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10408         if (*l == '@' && IS_AOP_PREG(result)) {
10409
10410         pic16_emitcode("mov","a,%s",l);
10411         pic16_aopPut(AOP(result),"a",offset);
10412         } else
10413         pic16_aopPut(AOP(result),l,offset);
10414       */
10415       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10416       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10417
10418       offset++;
10419     }
10420   }
10421
10422   /* mov the highest order bit to OVR */    
10423   tlbl = newiTempLabel(NULL);
10424   tlbl1= newiTempLabel(NULL);
10425
10426   size = AOP_SIZE(result);
10427   offset = size - 1;
10428
10429   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10430
10431   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10432
10433   /* offset should be 0, 1 or 3 */
10434   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10435   emitSKPNZ;
10436   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10437
10438   pic16_emitpcode(POC_MOVWF, pctemp);
10439
10440
10441   pic16_emitpLabel(tlbl->key);
10442
10443   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10444   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10445
10446   while(--size) {
10447     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10448   }
10449
10450   pic16_emitpcode(POC_DECFSZ,  pctemp);
10451   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10452   pic16_emitpLabel(tlbl1->key);
10453
10454   pic16_popReleaseTempReg(pctemp,1);
10455 #if 0
10456   size = AOP_SIZE(result);
10457   offset = size - 1;
10458   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10459   pic16_emitcode("rlc","a");
10460   pic16_emitcode("mov","ov,c");
10461   /* if it is only one byte then */
10462   if (size == 1) {
10463     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10464     MOVA(l);
10465     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10466     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10467     pic16_emitcode("mov","c,ov");
10468     pic16_emitcode("rrc","a");
10469     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10470     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10471     pic16_aopPut(AOP(result),"a",0);
10472     goto release ;
10473   }
10474
10475   reAdjustPreg(AOP(result));
10476   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10477   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10478   pic16_emitcode("mov","c,ov");
10479   while (size--) {
10480     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10481     MOVA(l);
10482     pic16_emitcode("rrc","a");         
10483     pic16_aopPut(AOP(result),"a",offset--);
10484   }
10485   reAdjustPreg(AOP(result));
10486   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10487   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10488
10489  release:
10490 #endif
10491
10492   pic16_freeAsmop(left,NULL,ic,TRUE);
10493   pic16_freeAsmop(result,NULL,ic,TRUE);
10494   pic16_freeAsmop(right,NULL,ic,TRUE);
10495 }
10496 #endif
10497
10498 #if !(USE_GENERIC_SIGNED_SHIFT)
10499 #warning This implementation of genRightShift() is incomplete!
10500 /*-----------------------------------------------------------------*/
10501 /* genRightShift - generate code for right shifting                */
10502 /*-----------------------------------------------------------------*/
10503 static void genRightShift (iCode *ic)
10504 {
10505     operand *right, *left, *result;
10506     sym_link *letype ;
10507     int size, offset;
10508     char *l;
10509     symbol *tlbl, *tlbl1 ;
10510
10511     /* if signed then we do it the hard way preserve the
10512     sign bit moving it inwards */
10513     letype = getSpec(operandType(IC_LEFT(ic)));
10514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10515
10516     if (!SPEC_USIGN(letype)) {
10517         genSignedRightShift (ic);
10518         return ;
10519     }
10520
10521     /* signed & unsigned types are treated the same : i.e. the
10522     signed is NOT propagated inwards : quoting from the
10523     ANSI - standard : "for E1 >> E2, is equivalent to division
10524     by 2**E2 if unsigned or if it has a non-negative value,
10525     otherwise the result is implementation defined ", MY definition
10526     is that the sign does not get propagated */
10527
10528     right = IC_RIGHT(ic);
10529     left  = IC_LEFT(ic);
10530     result = IC_RESULT(ic);
10531
10532     pic16_aopOp(right,ic,FALSE);
10533
10534     /* if the shift count is known then do it 
10535     as efficiently as possible */
10536     if (AOP_TYPE(right) == AOP_LIT) {
10537         genRightShiftLiteral (left,right,result,ic, 0);
10538         return ;
10539     }
10540
10541     /* shift count is unknown then we have to form 
10542     a loop get the loop count in B : Note: we take
10543     only the lower order byte since shifting
10544     more that 32 bits make no sense anyway, ( the
10545     largest size of an object can be only 32 bits ) */  
10546
10547     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10548     pic16_emitcode("inc","b");
10549     pic16_aopOp(left,ic,FALSE);
10550     pic16_aopOp(result,ic,FALSE);
10551
10552     /* now move the left to the result if they are not the
10553     same */
10554     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10555         AOP_SIZE(result) > 1) {
10556
10557         size = AOP_SIZE(result);
10558         offset=0;
10559         while (size--) {
10560             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10561             if (*l == '@' && IS_AOP_PREG(result)) {
10562
10563                 pic16_emitcode("mov","a,%s",l);
10564                 pic16_aopPut(AOP(result),"a",offset);
10565             } else
10566                 pic16_aopPut(AOP(result),l,offset);
10567             offset++;
10568         }
10569     }
10570
10571     tlbl = newiTempLabel(NULL);
10572     tlbl1= newiTempLabel(NULL);
10573     size = AOP_SIZE(result);
10574     offset = size - 1;
10575
10576     /* if it is only one byte then */
10577     if (size == 1) {
10578
10579       tlbl = newiTempLabel(NULL);
10580       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10581         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10582         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10583       }
10584
10585       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10586       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10587       pic16_emitpLabel(tlbl->key);
10588       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10589       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10590       emitSKPC;
10591       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10592
10593       goto release ;
10594     }
10595
10596     reAdjustPreg(AOP(result));
10597     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10598     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10599     CLRC;
10600     while (size--) {
10601         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10602         MOVA(l);
10603         pic16_emitcode("rrc","a");         
10604         pic16_aopPut(AOP(result),"a",offset--);
10605     }
10606     reAdjustPreg(AOP(result));
10607
10608     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10609     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10610
10611 release:
10612     pic16_freeAsmop(left,NULL,ic,TRUE);
10613     pic16_freeAsmop (right,NULL,ic,TRUE);
10614     pic16_freeAsmop(result,NULL,ic,TRUE);
10615 }
10616 #endif
10617
10618 #if (USE_GENERIC_SIGNED_SHIFT)
10619 /*-----------------------------------------------------------------*/
10620 /* genGenericShift - generates code for left or right shifting     */
10621 /*-----------------------------------------------------------------*/
10622 static void genGenericShift (iCode *ic, int isShiftLeft) {
10623   operand *left,*right, *result;
10624   int offset;
10625   int sign, signedCount;
10626   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10627   PIC_OPCODE pos_shift, neg_shift;
10628
10629   FENTRY;
10630
10631   right = IC_RIGHT(ic);
10632   left  = IC_LEFT(ic);
10633   result = IC_RESULT(ic);
10634
10635   pic16_aopOp(right,ic,FALSE);
10636   pic16_aopOp(left,ic,FALSE);
10637   pic16_aopOp(result,ic,TRUE);
10638
10639   sign = !SPEC_USIGN(operandType (left));
10640   signedCount = !SPEC_USIGN(operandType (right));
10641
10642   /* if the shift count is known then do it 
10643      as efficiently as possible */
10644   if (AOP_TYPE(right) == AOP_LIT) {
10645     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10646     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10647     // we should modify right->aopu.aop_lit here!
10648     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10649     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10650     if (isShiftLeft)
10651       pic16_genLeftShiftLiteral (left,right,result,ic);
10652     else
10653       genRightShiftLiteral (left,right,result,ic, sign);
10654
10655     goto release;
10656   } // if (right is literal)
10657
10658   /* shift count is unknown then we have to form a loop.
10659    * Note: we take only the lower order byte since shifting
10660    * more than 32 bits make no sense anyway, ( the
10661    * largest size of an object can be only 32 bits )
10662    * Note: we perform arithmetic shifts if the left operand is
10663    * signed and we do an (effective) right shift, i. e. we
10664    * shift in the sign bit from the left. */
10665    
10666   label_complete = newiTempLabel ( NULL );
10667   label_loop_pos = newiTempLabel ( NULL );
10668   label_loop_neg = NULL;
10669   label_negative = NULL;
10670   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10671   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10672
10673   if (signedCount) {
10674     // additional labels needed
10675     label_loop_neg = newiTempLabel ( NULL );
10676     label_negative = newiTempLabel ( NULL );
10677   } // if
10678
10679   // copy source to result -- this will effectively truncate the left operand to the size of result!
10680   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10681   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10682   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10683     pic16_mov2f (AOP(result),AOP(left), offset);
10684   } // for
10685
10686   // if result is longer than left, fill with zeros (or sign)
10687   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10688     if (sign && AOP_SIZE(left) > 0) {
10689       // shift signed operand -- fill with sign
10690       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10691       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10692       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10693       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10694         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10695       } // for
10696     } else {
10697       // shift unsigned operand -- fill result with zeros
10698       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10699         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10700       } // for
10701     }
10702   } // if (size mismatch)
10703
10704   pic16_mov2w (AOP(right), 0);
10705   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10706   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10707   
10708 #if 0
10709   // perform a shift by one (shift count is positive)
10710   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10711   // 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])
10712   pic16_emitpLabel (label_loop_pos->key);
10713   emitCLRC;
10714   if (sign && (pos_shift == POC_RRCF)) {
10715     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10716     emitSETC;
10717   } // if
10718   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10719   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10720   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10721 #else
10722   // perform a shift by one (shift count is positive)
10723   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10724   // 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])
10725   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10726   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10727   emitCLRC;
10728   pic16_emitpLabel (label_loop_pos->key);
10729   if (sign && (pos_shift == POC_RRCF)) {
10730     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10731     emitSETC;
10732   } // if
10733   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10734   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10735   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10736   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10737 #endif
10738
10739   if (signedCount) {
10740     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10741
10742     pic16_emitpLabel (label_negative->key);
10743     // perform a shift by -1 (shift count is negative)
10744     // 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)
10745     emitCLRC;
10746     pic16_emitpLabel (label_loop_neg->key);
10747     if (sign && (neg_shift == POC_RRCF)) {
10748       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10749       emitSETC;
10750     } // if
10751     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10752     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10753     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10754     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10755   } // if (signedCount)
10756
10757   pic16_emitpLabel (label_complete->key);
10758
10759 release:
10760   pic16_freeAsmop (right,NULL,ic,TRUE);
10761   pic16_freeAsmop(left,NULL,ic,TRUE);
10762   pic16_freeAsmop(result,NULL,ic,TRUE);
10763 }
10764
10765 static void genLeftShift (iCode *ic) {
10766   genGenericShift (ic, 1);
10767 }
10768
10769 static void genRightShift (iCode *ic) {
10770   genGenericShift (ic, 0);
10771 }
10772 #endif
10773
10774
10775 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10776 void pic16_loadFSR0(operand *op, int lit)
10777 {
10778   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10779     if (AOP_TYPE(op) == AOP_LIT) {
10780       /* handle 12 bit integers correctly */
10781       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10782       if ((val & 0x0fff) != val) {
10783         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10784                 val, (val & 0x0fff) );
10785         val &= 0x0fff;
10786       }
10787       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10788     } else {
10789       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10790     }
10791   } else {
10792     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10793     // set up FSR0 with address of result
10794     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10795     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10796   }
10797 }
10798
10799 /*----------------------------------------------------------------*/
10800 /* pic16_derefPtr - move one byte from the location ptr points to */
10801 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10802 /*                  to the location ptr points to (doWrite != 0)   */
10803 /*----------------------------------------------------------------*/
10804 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10805 {
10806   if (!IS_PTR(operandType(ptr)))
10807   {
10808     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10809     else pic16_mov2w (AOP(ptr), 0);
10810     return;
10811   }
10812
10813   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10814   /* We might determine pointer type right here: */
10815   p_type = DCL_TYPE(operandType(ptr));
10816
10817   switch (p_type) {
10818     case FPOINTER:
10819     case POINTER:
10820       if (!fsr0_setup || !*fsr0_setup)
10821       {
10822         pic16_loadFSR0( ptr, 0 );
10823         if (fsr0_setup) *fsr0_setup = 1;
10824       }
10825       if (doWrite)
10826         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10827       else
10828         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10829       break;
10830
10831     case GPOINTER:
10832       if (AOP(ptr)->aopu.aop_reg[2]) {
10833         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10834         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10835         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10836         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10837         pic16_mov2w(AOP(ptr), 2);
10838         pic16_callGenericPointerRW(doWrite, 1);
10839       } else {
10840         // data pointer (just 2 byte given)
10841         if (!fsr0_setup || !*fsr0_setup)
10842         {
10843           pic16_loadFSR0( ptr, 0 );
10844           if (fsr0_setup) *fsr0_setup = 1;
10845         }
10846         if (doWrite)
10847           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10848         else
10849           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10850       }
10851       break;
10852
10853     default:
10854       assert (0 && "invalid pointer type specified");
10855       break;
10856   }
10857 }
10858
10859 /*-----------------------------------------------------------------*/
10860 /* genUnpackBits - generates code for unpacking bits               */
10861 /*-----------------------------------------------------------------*/
10862 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10863 {    
10864   int shCnt ;
10865   sym_link *etype, *letype;
10866   int blen=0, bstr=0;
10867   int lbstr;
10868   int same;
10869   pCodeOp *op;
10870
10871   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10872   etype = getSpec(operandType(result));
10873   letype = getSpec(operandType(left));
10874
10875   //    if(IS_BITFIELD(etype)) {
10876   blen = SPEC_BLEN(etype);
10877   bstr = SPEC_BSTR(etype);
10878   //    }
10879
10880   lbstr = SPEC_BSTR( letype );
10881
10882   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10883       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10884
10885 #if 1
10886   if((blen == 1) && (bstr < 8)
10887       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10888     /* it is a single bit, so use the appropriate bit instructions */
10889     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10890
10891     same = pic16_sameRegs(AOP(left),AOP(result));
10892     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10893     pic16_emitpcode(POC_CLRF, op);
10894
10895     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10896       /* workaround to reduce the extra lfsr instruction */
10897       pic16_emitpcode(POC_BTFSC,
10898           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10899     } else {
10900       assert (PIC_IS_DATA_PTR (operandType(left)));
10901       pic16_loadFSR0 (left, 0);
10902       pic16_emitpcode(POC_BTFSC,
10903           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10904     }
10905
10906     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10907       /* unsigned bitfields result in either 0 or 1 */
10908       pic16_emitpcode(POC_INCF, op);
10909     } else {
10910       /* signed bitfields result in either 0 or -1 */
10911       pic16_emitpcode(POC_DECF, op);
10912     }
10913     if (same) {
10914       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10915     }
10916
10917     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10918     return;
10919   }
10920
10921 #endif
10922
10923   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10924     // access symbol directly
10925     pic16_mov2w (AOP(left), 0);
10926   } else {
10927     pic16_derefPtr (left, ptype, 0, NULL);
10928   }
10929
10930   /* if we have bitdisplacement then it fits   */
10931   /* into this byte completely or if length is */
10932   /* less than a byte                          */
10933   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10934
10935     /* shift right acc */
10936     AccRsh(shCnt, 0);
10937
10938     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10939           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10940
10941     /* VR -- normally I would use the following, but since we use the hack,
10942      * to avoid the masking from AccRsh, why not mask it right now? */
10943
10944     /*
10945        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10946      */
10947
10948     /* extend signed bitfields to 8 bits */
10949     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10950     {
10951       assert (blen + bstr > 0);
10952       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10953       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10954     }
10955
10956     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10957
10958     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10959     return ;
10960   }
10961
10962   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10963   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10964   exit(EXIT_FAILURE);
10965
10966   return ;
10967 }
10968
10969
10970 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10971 {
10972   int size, offset = 0, leoffset=0 ;
10973
10974         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10975         pic16_aopOp(result, ic, TRUE);
10976
10977         FENTRY;
10978
10979         size = AOP_SIZE(result);
10980 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10981
10982
10983 #if 1
10984         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10985                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10986                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10987                 goto release;
10988         }
10989 #endif
10990
10991         if(AOP(left)->aopu.pcop->type == PO_DIR)
10992                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10993
10994         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10995
10996         while (size--) {
10997                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10998                 
10999 //              pic16_DumpOp("(result)",result);
11000                 if(is_LitAOp(AOP(result))) {
11001                         pic16_mov2w(AOP(left), offset); // patch 8
11002                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11003                 } else {
11004                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11005                                 pic16_popGet(AOP(left), offset), //patch 8
11006                                 pic16_popGet(AOP(result), offset)));
11007                 }
11008
11009                 offset++;
11010                 leoffset++;
11011         }
11012
11013 release:
11014     pic16_freeAsmop(result,NULL,ic,TRUE);
11015 }
11016
11017
11018
11019 /*-----------------------------------------------------------------*/
11020 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11021 /*-----------------------------------------------------------------*/
11022 static void genNearPointerGet (operand *left, 
11023                                operand *result, 
11024                                iCode *ic)
11025 {
11026 //  asmop *aop = NULL;
11027   //regs *preg = NULL ;
11028   sym_link *rtype, *retype;
11029   sym_link *ltype, *letype;
11030
11031     FENTRY;
11032     
11033     rtype = operandType(result);
11034     retype= getSpec(rtype);
11035     ltype = operandType(left);
11036     letype= getSpec(ltype);
11037     
11038     pic16_aopOp(left,ic,FALSE);
11039
11040 //    pic16_DumpOp("(left)",left);
11041 //    pic16_DumpOp("(result)",result);
11042
11043     /* if left is rematerialisable and
11044      * result is not bit variable type and
11045      * the left is pointer to data space i.e
11046      * lower 128 bytes of space */
11047     
11048     if (AOP_TYPE(left) == AOP_PCODE
11049       && !IS_BITFIELD(retype)
11050       && DCL_TYPE(ltype) == POINTER) {
11051
11052         genDataPointerGet (left,result,ic);
11053         pic16_freeAsmop(left, NULL, ic, TRUE);
11054         return ;
11055     }
11056     
11057     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11058     pic16_aopOp (result,ic,TRUE);
11059     
11060     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11061
11062 #if 1
11063     if(IS_BITFIELD( retype )
11064       && (SPEC_BLEN(operandType(result))==1)
11065     ) {
11066       iCode *nextic;
11067       pCodeOp *jop;
11068       int bitstrt, bytestrt;
11069
11070         /* if this is bitfield of size 1, see if we are checking the value
11071          * of a single bit in an if-statement,
11072          * if yes, then don't generate usual code, but execute the
11073          * genIfx directly -- VR */
11074
11075         nextic = ic->next;
11076
11077         /* CHECK: if next iCode is IFX
11078          * and current result operand is nextic's conditional operand
11079          * and current result operand live ranges ends at nextic's key number
11080          */
11081         if((nextic->op == IFX)
11082           && (result == IC_COND(nextic))
11083           && (OP_LIVETO(result) == nextic->seq)
11084           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11085           ) {
11086             /* everything is ok then */
11087             /* find a way to optimize the genIfx iCode */
11088
11089             bytestrt = SPEC_BSTR(operandType(result))/8;
11090             bitstrt = SPEC_BSTR(operandType(result))%8;
11091             
11092             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11093
11094             genIfxpCOpJump(nextic, jop);
11095             
11096             pic16_freeAsmop(left, NULL, ic, TRUE);
11097             pic16_freeAsmop(result, NULL, ic, TRUE);
11098             return;
11099         }
11100     }
11101 #endif
11102
11103     /* if bitfield then unpack the bits */
11104     if (IS_BITFIELD(letype)) 
11105       genUnpackBits (result, left, NULL, POINTER);
11106     else {
11107       /* we have can just get the values */
11108       int size = AOP_SIZE(result);
11109       int offset = 0;   
11110         
11111       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11112
11113       pic16_loadFSR0( left, 0 );
11114
11115       while(size--) {
11116         if(size) {
11117           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11118                 pic16_popGet(AOP(result), offset++)));
11119         } else {
11120           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11121                 pic16_popGet(AOP(result), offset++)));
11122         }
11123       }
11124     }
11125
11126 #if 0
11127     /* now some housekeeping stuff */
11128     if (aop) {
11129       /* we had to allocate for this iCode */
11130       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11131       pic16_freeAsmop(NULL,aop,ic,TRUE);
11132     } else { 
11133       /* we did not allocate which means left
11134        * already in a pointer register, then
11135        * if size > 0 && this could be used again
11136        * we have to point it back to where it 
11137        * belongs */
11138       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11139       if (AOP_SIZE(result) > 1
11140         && !OP_SYMBOL(left)->remat
11141         && ( OP_SYMBOL(left)->liveTo > ic->seq
11142             || ic->depth )) {
11143 //        int size = AOP_SIZE(result) - 1;
11144 //        while (size--)
11145 //          pic16_emitcode("dec","%s",rname);
11146         }
11147     }
11148 #endif
11149
11150     /* done */
11151     pic16_freeAsmop(left,NULL,ic,TRUE);
11152     pic16_freeAsmop(result,NULL,ic,TRUE);
11153 }
11154
11155 /*-----------------------------------------------------------------*/
11156 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11157 /*-----------------------------------------------------------------*/
11158 static void genPagedPointerGet (operand *left, 
11159                                operand *result, 
11160                                iCode *ic)
11161 {
11162     asmop *aop = NULL;
11163     regs *preg = NULL ;
11164     char *rname ;
11165     sym_link *rtype, *retype;    
11166
11167     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11168
11169     rtype = operandType(result);
11170     retype= getSpec(rtype);
11171     
11172     pic16_aopOp(left,ic,FALSE);
11173
11174   /* if the value is already in a pointer register
11175        then don't need anything more */
11176     if (!AOP_INPREG(AOP(left))) {
11177         /* otherwise get a free pointer register */
11178         aop = newAsmop(0);
11179         preg = getFreePtr(ic,&aop,FALSE);
11180         pic16_emitcode("mov","%s,%s",
11181                 preg->name,
11182                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11183         rname = preg->name ;
11184     } else
11185         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11186     
11187     pic16_freeAsmop(left,NULL,ic,TRUE);
11188     pic16_aopOp (result,ic,TRUE);
11189
11190     /* if bitfield then unpack the bits */
11191     if (IS_BITFIELD(retype)) 
11192         genUnpackBits (result,left,rname,PPOINTER);
11193     else {
11194         /* we have can just get the values */
11195         int size = AOP_SIZE(result);
11196         int offset = 0 ;        
11197         
11198         while (size--) {
11199             
11200             pic16_emitcode("movx","a,@%s",rname);
11201             pic16_aopPut(AOP(result),"a",offset);
11202             
11203             offset++ ;
11204             
11205             if (size)
11206                 pic16_emitcode("inc","%s",rname);
11207         }
11208     }
11209
11210     /* now some housekeeping stuff */
11211     if (aop) {
11212         /* we had to allocate for this iCode */
11213         pic16_freeAsmop(NULL,aop,ic,TRUE);
11214     } else { 
11215         /* we did not allocate which means left
11216            already in a pointer register, then
11217            if size > 0 && this could be used again
11218            we have to point it back to where it 
11219            belongs */
11220         if (AOP_SIZE(result) > 1 &&
11221             !OP_SYMBOL(left)->remat &&
11222             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11223               ic->depth )) {
11224             int size = AOP_SIZE(result) - 1;
11225             while (size--)
11226                 pic16_emitcode("dec","%s",rname);
11227         }
11228     }
11229
11230     /* done */
11231     pic16_freeAsmop(result,NULL,ic,TRUE);
11232     
11233         
11234 }
11235
11236 #if 0
11237 /* This code is not adjusted to PIC16 and fails utterly.
11238  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11239
11240 /*-----------------------------------------------------------------*/
11241 /* genFarPointerGet - gget value from far space                    */
11242 /*-----------------------------------------------------------------*/
11243 static void genFarPointerGet (operand *left,
11244                               operand *result, iCode *ic)
11245 {
11246     int size, offset ;
11247     sym_link *retype = getSpec(operandType(result));
11248
11249     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11250
11251     pic16_aopOp(left,ic,FALSE);
11252
11253     /* if the operand is already in dptr 
11254     then we do nothing else we move the value to dptr */
11255     if (AOP_TYPE(left) != AOP_STR) {
11256         /* if this is remateriazable */
11257         if (AOP_TYPE(left) == AOP_IMMD)
11258             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11259         else { /* we need to get it byte by byte */
11260             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11261             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11262             if (options.model == MODEL_FLAT24)
11263             {
11264                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11265             }
11266         }
11267     }
11268     /* so dptr know contains the address */
11269     pic16_freeAsmop(left,NULL,ic,TRUE);
11270     pic16_aopOp(result,ic,TRUE);
11271
11272     /* if bit then unpack */
11273     if (IS_BITFIELD(retype)) 
11274         genUnpackBits(result,left,"dptr",FPOINTER);
11275     else {
11276         size = AOP_SIZE(result);
11277         offset = 0 ;
11278
11279         while (size--) {
11280             pic16_emitcode("movx","a,@dptr");
11281             pic16_aopPut(AOP(result),"a",offset++);
11282             if (size)
11283                 pic16_emitcode("inc","dptr");
11284         }
11285     }
11286
11287     pic16_freeAsmop(result,NULL,ic,TRUE);
11288 }
11289 #endif
11290
11291 #if 0
11292 /*-----------------------------------------------------------------*/
11293 /* genCodePointerGet - get value from code space                  */
11294 /*-----------------------------------------------------------------*/
11295 static void genCodePointerGet (operand *left,
11296                                 operand *result, iCode *ic)
11297 {
11298     int size, offset ;
11299     sym_link *retype = getSpec(operandType(result));
11300
11301     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11302
11303     pic16_aopOp(left,ic,FALSE);
11304
11305     /* if the operand is already in dptr 
11306     then we do nothing else we move the value to dptr */
11307     if (AOP_TYPE(left) != AOP_STR) {
11308         /* if this is remateriazable */
11309         if (AOP_TYPE(left) == AOP_IMMD)
11310             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11311         else { /* we need to get it byte by byte */
11312             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11313             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11314             if (options.model == MODEL_FLAT24)
11315             {
11316                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11317             }
11318         }
11319     }
11320     /* so dptr know contains the address */
11321     pic16_freeAsmop(left,NULL,ic,TRUE);
11322     pic16_aopOp(result,ic,FALSE);
11323
11324     /* if bit then unpack */
11325     if (IS_BITFIELD(retype)) 
11326         genUnpackBits(result,left,"dptr",CPOINTER);
11327     else {
11328         size = AOP_SIZE(result);
11329         offset = 0 ;
11330
11331         while (size--) {
11332             pic16_emitcode("clr","a");
11333             pic16_emitcode("movc","a,@a+dptr");
11334             pic16_aopPut(AOP(result),"a",offset++);
11335             if (size)
11336                 pic16_emitcode("inc","dptr");
11337         }
11338     }
11339
11340     pic16_freeAsmop(result,NULL,ic,TRUE);
11341 }
11342 #endif
11343
11344 #if 0
11345 /*-----------------------------------------------------------------*/
11346 /* genGenPointerGet - gget value from generic pointer space        */
11347 /*-----------------------------------------------------------------*/
11348 static void genGenPointerGet (operand *left,
11349                               operand *result, iCode *ic)
11350 {
11351   int size, offset, lit;
11352   sym_link *retype = getSpec(operandType(result));
11353
11354         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11355         pic16_aopOp(left,ic,FALSE);
11356         pic16_aopOp(result,ic,FALSE);
11357         size = AOP_SIZE(result);
11358
11359         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11360
11361         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11362
11363                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11364                 // load FSR0 from immediate
11365                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11366
11367 //              pic16_loadFSR0( left );
11368
11369                 offset = 0;
11370                 while(size--) {
11371                         if(size) {
11372                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11373                         } else {
11374                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11375                         }
11376                         offset++;
11377                 }
11378                 goto release;
11379
11380         }
11381         else { /* we need to get it byte by byte */
11382                 // set up FSR0 with address from left
11383                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11384                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11385                 
11386                 offset = 0 ;
11387
11388                 while(size--) {
11389                         if(size) {
11390                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11391                         } else {
11392                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11393                         }
11394                         offset++;
11395                 }
11396                 goto release;
11397         }
11398
11399   /* if bit then unpack */
11400         if (IS_BITFIELD(retype)) 
11401                 genUnpackBits(result,left,"BAD",GPOINTER);
11402
11403         release:
11404         pic16_freeAsmop(left,NULL,ic,TRUE);
11405         pic16_freeAsmop(result,NULL,ic,TRUE);
11406
11407 }
11408 #endif
11409
11410
11411 /*-----------------------------------------------------------------*/
11412 /* genGenPointerGet - gget value from generic pointer space        */
11413 /*-----------------------------------------------------------------*/
11414 static void genGenPointerGet (operand *left,
11415                               operand *result, iCode *ic)
11416 {
11417   int size, offset, lit;
11418   sym_link *letype = getSpec(operandType(left));
11419
11420     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11421     pic16_aopOp(left,ic,FALSE);
11422     pic16_aopOp(result,ic,TRUE);
11423     size = AOP_SIZE(result);
11424
11425     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11426   
11427     /* if bit then unpack */
11428     if (IS_BITFIELD(letype)) {
11429       genUnpackBits(result,left,"BAD",GPOINTER);
11430       goto release;
11431     }
11432
11433     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11434
11435       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11436       // load FSR0 from immediate
11437       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11438
11439       werror(W_POSSBUG2, __FILE__, __LINE__);
11440
11441       offset = 0;
11442       while(size--) {
11443         if(size) {
11444           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11445         } else {
11446           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11447         }
11448         offset++;
11449       }
11450
11451       goto release;
11452
11453     } else { /* we need to get it byte by byte */
11454
11455       /* set up WREG:PRODL:FSR0L with address from left */
11456       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11457       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11458       pic16_mov2w(AOP(left), 2);
11459       pic16_callGenericPointerRW(0, size);
11460       
11461       assignResultValue(result, size, 1);
11462       
11463       goto release;
11464     }
11465
11466 release:
11467   pic16_freeAsmop(left,NULL,ic,TRUE);
11468   pic16_freeAsmop(result,NULL,ic,TRUE);
11469 }
11470
11471 /*-----------------------------------------------------------------*/
11472 /* genConstPointerGet - get value from const generic pointer space */
11473 /*-----------------------------------------------------------------*/
11474 static void genConstPointerGet (operand *left,
11475                                 operand *result, iCode *ic)
11476 {
11477   //sym_link *retype = getSpec(operandType(result));
11478   // symbol *albl = newiTempLabel(NULL);        // patch 15
11479   // symbol *blbl = newiTempLabel(NULL);        //
11480   // PIC_OPCODE poc;                            // patch 15
11481   int size;
11482   int offset = 0;
11483
11484   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11485   pic16_aopOp(left,ic,FALSE);
11486   pic16_aopOp(result,ic,TRUE);
11487   size = AOP_SIZE(result);
11488
11489   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11490
11491   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11492
11493   // set up table pointer
11494   if( (AOP_TYPE(left) == AOP_PCODE) 
11495       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11496           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11497     {
11498       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11499       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11500       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11501       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11502       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11503       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11504   } else {
11505     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11506     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11507     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11508   }
11509
11510   while(size--) {
11511     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11512     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11513     offset++;
11514   }
11515     
11516   pic16_freeAsmop(left,NULL,ic,TRUE);
11517   pic16_freeAsmop(result,NULL,ic,TRUE);
11518 }
11519
11520
11521 /*-----------------------------------------------------------------*/
11522 /* genPointerGet - generate code for pointer get                   */
11523 /*-----------------------------------------------------------------*/
11524 static void genPointerGet (iCode *ic)
11525 {
11526   operand *left, *result ;
11527   sym_link *type, *etype;
11528   int p_type;
11529
11530     FENTRY;
11531     
11532     left = IC_LEFT(ic);
11533     result = IC_RESULT(ic) ;
11534
11535     /* depending on the type of pointer we need to
11536     move it to the correct pointer register */
11537     type = operandType(left);
11538     etype = getSpec(type);
11539
11540 #if 0
11541     if (IS_PTR_CONST(type))
11542 #else
11543     if (IS_CODEPTR(type))
11544 #endif
11545       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11546
11547     /* if left is of type of pointer then it is simple */
11548     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11549       p_type = DCL_TYPE(type);
11550     else {
11551       /* we have to go by the storage class */
11552       p_type = PTR_TYPE(SPEC_OCLS(etype));
11553
11554       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11555
11556       if (SPEC_OCLS(etype)->codesp ) {
11557         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11558         //p_type = CPOINTER ;   
11559       } else
11560       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11561         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11562         /*p_type = FPOINTER ;*/ 
11563       } else
11564       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11565         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11566         /* p_type = PPOINTER; */
11567       } else
11568       if (SPEC_OCLS(etype) == idata ) {
11569         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11570         /* p_type = IPOINTER; */
11571       } else {
11572         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11573         /* p_type = POINTER ; */
11574       }
11575     }
11576
11577     /* now that we have the pointer type we assign
11578     the pointer values */
11579     switch (p_type) {
11580       case POINTER:     
11581       case FPOINTER:
11582       case IPOINTER:
11583         genNearPointerGet (left,result,ic);
11584         break;
11585
11586       case PPOINTER:
11587         genPagedPointerGet(left,result,ic);
11588         break;
11589
11590 #if 0
11591       /* PICs do not support FAR pointers... */
11592       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11593       case FPOINTER:
11594         genFarPointerGet (left,result,ic);
11595         break;
11596 #endif
11597
11598       case CPOINTER:
11599         genConstPointerGet (left,result,ic);
11600         //pic16_emitcodePointerGet (left,result,ic);
11601         break;
11602
11603       case GPOINTER:
11604 #if 0
11605       if (IS_PTR_CONST(type))
11606         genConstPointerGet (left,result,ic);
11607       else
11608 #endif
11609         genGenPointerGet (left,result,ic);
11610       break;
11611
11612     default:
11613       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11614               "genPointerGet: illegal pointer type");
11615     
11616     }
11617 }
11618
11619 /*-----------------------------------------------------------------*/
11620 /* genPackBits - generates code for packed bit storage             */
11621 /*-----------------------------------------------------------------*/
11622 static void genPackBits (sym_link    *etype , operand *result,
11623                          operand *right ,
11624                          char *rname, int p_type)
11625 {
11626   int shCnt = 0 ;
11627   int offset = 0  ;
11628   int rLen = 0 ;
11629   int blen, bstr ;   
11630   int shifted_and_masked = 0;
11631   unsigned long lit = (unsigned long)-1;
11632   sym_link *retype;
11633
11634   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11635   blen = SPEC_BLEN(etype);
11636   bstr = SPEC_BSTR(etype);
11637
11638   retype = getSpec(operandType(right));
11639
11640   if(AOP_TYPE(right) == AOP_LIT) {
11641     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11642     
11643     if((blen == 1) && (bstr < 8)) {
11644       /* it is a single bit, so use the appropriate bit instructions */
11645
11646       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11647
11648       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11649         /* workaround to reduce the extra lfsr instruction */
11650         if(lit) {
11651           pic16_emitpcode(POC_BSF,
11652               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11653         } else {
11654           pic16_emitpcode(POC_BCF,
11655               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11656         }
11657       } else {
11658         if (PIC_IS_DATA_PTR(operandType(result))) {
11659           pic16_loadFSR0(result, 0);
11660           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11661               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11662         } else {
11663           /* get old value */
11664           pic16_derefPtr (result, p_type, 0, NULL);
11665           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11666               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11667           /* write back new value */
11668           pic16_derefPtr (result, p_type, 1, NULL);
11669         }
11670       }
11671
11672       return;
11673     }
11674     /* IORLW below is more efficient */
11675     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11676     lit = (lit & ((1UL << blen) - 1)) << bstr;
11677     shifted_and_masked = 1;
11678     offset++;
11679   } else
11680     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11681         && IS_BITFIELD(retype) 
11682         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11683         && (blen == 1)) {
11684       int rblen, rbstr;
11685
11686       rblen = SPEC_BLEN( retype );
11687       rbstr = SPEC_BSTR( retype );
11688
11689       if(IS_BITFIELD(etype)) {
11690         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11691         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11692       } else {
11693         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11694       }
11695
11696       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11697
11698       if(IS_BITFIELD(etype)) {
11699         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11700       } else {
11701         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11702       }
11703
11704       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11705
11706       return;
11707     } else {
11708       /* move right to W */
11709       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11710     }
11711
11712   /* if the bit length is less than or   */
11713   /* it exactly fits a byte then         */
11714   if((shCnt=SPEC_BSTR(etype))
11715       || SPEC_BLEN(etype) <= 8 )  {
11716     int fsr0_setup = 0;
11717
11718     if (blen != 8 || bstr != 0) {
11719       // we need to combine the value with the old value
11720       if(!shifted_and_masked)
11721       {
11722         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11723
11724         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11725             SPEC_BSTR(etype), SPEC_BLEN(etype));
11726
11727         /* shift left acc, do NOT mask the result again */
11728         AccLsh(shCnt, 0);
11729
11730         /* using PRODH as a temporary register here */
11731         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11732       }
11733
11734       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11735         || IS_DIRECT(result)) {
11736         /* access symbol directly */
11737         pic16_mov2w (AOP(result), 0);
11738       } else {
11739         /* get old value */
11740         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11741       }
11742 #if 1
11743       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11744             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11745                             (unsigned char)(0xff >> (8-bstr))) ));
11746       if (!shifted_and_masked) {
11747         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11748       } else {
11749         /* We have the shifted and masked (literal) right value in `lit' */
11750         if (lit != 0)
11751           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11752       }
11753     } // if (blen != 8 || bstr != 0)
11754
11755     /* write new value back */
11756     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11757         || IS_DIRECT(result)) {
11758       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11759     } else {
11760       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11761     }
11762 #endif
11763
11764     return;
11765   }
11766
11767
11768 #if 0
11769   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11770   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11771   exit(EXIT_FAILURE);
11772 #endif
11773
11774
11775   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11776   rLen = SPEC_BLEN(etype)-8;
11777
11778   /* now generate for lengths greater than one byte */
11779   while (1) {
11780     rLen -= 8 ;
11781     if (rLen <= 0 ) {
11782       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11783       break ;
11784     }
11785
11786     switch (p_type) {
11787       case POINTER:
11788         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11789         break;
11790
11791         /*
11792            case FPOINTER:
11793            MOVA(l);
11794            pic16_emitcode("movx","@dptr,a");
11795            break;
11796
11797            case GPOINTER:
11798            MOVA(l);
11799            DEBUGpic16_emitcode(";lcall","__gptrput");
11800            break;  
11801          */
11802       default:
11803         assert(0);
11804     }   
11805
11806
11807     pic16_mov2w(AOP(right), offset++);
11808   }
11809
11810   /* last last was not complete */
11811   if (rLen)   {
11812     /* save the byte & read byte */
11813     switch (p_type) {
11814       case POINTER:
11815         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11816         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11817         break;
11818
11819         /*
11820            case FPOINTER:
11821            pic16_emitcode ("mov","b,a");
11822            pic16_emitcode("movx","a,@dptr");
11823            break;
11824
11825            case GPOINTER:
11826            pic16_emitcode ("push","b");
11827            pic16_emitcode ("push","acc");
11828            pic16_emitcode ("lcall","__gptrget");
11829            pic16_emitcode ("pop","b");
11830            break;
11831          */
11832       default:
11833         assert(0);
11834     }
11835     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11836     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11837     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11838     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11839     //        pic16_emitcode ("orl","a,b");
11840   }
11841
11842   //    if (p_type == GPOINTER)
11843   //        pic16_emitcode("pop","b");
11844
11845   switch (p_type) {
11846
11847     case POINTER:
11848       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11849       //        pic16_emitcode("mov","@%s,a",rname);
11850       break;
11851       /*
11852          case FPOINTER:
11853          pic16_emitcode("movx","@dptr,a");
11854          break;
11855
11856          case GPOINTER:
11857          DEBUGpic16_emitcode(";lcall","__gptrput");
11858          break;                 
11859        */
11860     default:
11861       assert(0);
11862   }
11863
11864   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11865 }
11866
11867 /*-----------------------------------------------------------------*/
11868 /* genDataPointerSet - remat pointer to data space                 */
11869 /*-----------------------------------------------------------------*/
11870 static void genDataPointerSet(operand *right,
11871                               operand *result,
11872                               iCode *ic)
11873 {
11874   int size, offset = 0, resoffset=0 ;
11875
11876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11877     pic16_aopOp(right,ic,FALSE);
11878
11879     size = AOP_SIZE(right);
11880
11881 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11882
11883 #if 0
11884     if ( AOP_TYPE(result) == AOP_PCODE) {
11885       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11886               AOP(result)->aopu.pcop->name,
11887                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11888               PCOR(AOP(result)->aopu.pcop)->instance:
11889               PCOI(AOP(result)->aopu.pcop)->offset);
11890     }
11891 #endif
11892
11893     if(AOP(result)->aopu.pcop->type == PO_DIR)
11894       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11895
11896     while (size--) {
11897       if (AOP_TYPE(right) == AOP_LIT) {
11898         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11899         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11900       } else {
11901         pic16_mov2w(AOP(right), offset);
11902         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11903       }
11904       offset++;
11905       resoffset++;
11906     }
11907
11908     pic16_freeAsmop(right,NULL,ic,TRUE);
11909 }
11910
11911
11912
11913 /*-----------------------------------------------------------------*/
11914 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11915 /*-----------------------------------------------------------------*/
11916 static void genNearPointerSet (operand *right,
11917                                operand *result, 
11918                                iCode *ic)
11919 {
11920   asmop *aop = NULL;
11921   sym_link *retype;
11922   sym_link *ptype = operandType(result);
11923   sym_link *resetype;
11924     
11925     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11926     retype= getSpec(operandType(right));
11927     resetype = getSpec(operandType(result));
11928   
11929     pic16_aopOp(result,ic,FALSE);
11930     
11931     /* if the result is rematerializable &
11932      * in data space & not a bit variable */
11933         
11934     /* and result is not a bit variable */
11935     if (AOP_TYPE(result) == AOP_PCODE
11936 //      && AOP_TYPE(result) == AOP_IMMD
11937       && DCL_TYPE(ptype) == POINTER
11938       && !IS_BITFIELD(retype)
11939       && !IS_BITFIELD(resetype)) {
11940
11941         genDataPointerSet (right,result,ic);
11942         pic16_freeAsmop(result,NULL,ic,TRUE);
11943       return;
11944     }
11945
11946     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11947     pic16_aopOp(right,ic,FALSE);
11948     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11949
11950     /* if bitfield then unpack the bits */
11951     if (IS_BITFIELD(resetype)) {
11952       genPackBits (resetype, result, right, NULL, POINTER);
11953     } else {
11954       /* we have can just get the values */
11955       int size = AOP_SIZE(right);
11956       int offset = 0 ;    
11957
11958         pic16_loadFSR0(result, 0);
11959             
11960         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11961         while (size--) {
11962           if (AOP_TYPE(right) == AOP_LIT) {
11963             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11964             if (size) {
11965               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11966             } else {
11967               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11968             }
11969           } else { // no literal
11970             if(size) {
11971               pic16_emitpcode(POC_MOVFF,
11972                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11973                   pic16_popCopyReg(&pic16_pc_postinc0)));
11974             } else {
11975               pic16_emitpcode(POC_MOVFF,
11976                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11977                   pic16_popCopyReg(&pic16_pc_indf0)));
11978             }
11979           }
11980           
11981           offset++;
11982         }
11983     }
11984
11985     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11986     /* now some housekeeping stuff */
11987     if (aop) {
11988       /* we had to allocate for this iCode */
11989       pic16_freeAsmop(NULL,aop,ic,TRUE);
11990     } else { 
11991       /* we did not allocate which means left
11992        * already in a pointer register, then
11993        * if size > 0 && this could be used again
11994        * we have to point it back to where it 
11995        * belongs */
11996       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11997       if (AOP_SIZE(right) > 1
11998         && !OP_SYMBOL(result)->remat
11999         && ( OP_SYMBOL(result)->liveTo > ic->seq
12000         || ic->depth )) {
12001
12002           int size = AOP_SIZE(right) - 1;
12003
12004             while (size--)
12005               pic16_emitcode("decf","fsr0,f");
12006               //pic16_emitcode("dec","%s",rname);
12007       }
12008     }
12009
12010     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12011     /* done */
12012 //release:
12013     pic16_freeAsmop(right,NULL,ic,TRUE);
12014     pic16_freeAsmop(result,NULL,ic,TRUE);
12015 }
12016
12017 /*-----------------------------------------------------------------*/
12018 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12019 /*-----------------------------------------------------------------*/
12020 static void genPagedPointerSet (operand *right,
12021                                operand *result, 
12022                                iCode *ic)
12023 {
12024     asmop *aop = NULL;
12025     regs *preg = NULL ;
12026     char *rname , *l;
12027     sym_link *retype;
12028        
12029     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12030
12031     retype= getSpec(operandType(right));
12032     
12033     pic16_aopOp(result,ic,FALSE);
12034     
12035     /* if the value is already in a pointer register
12036        then don't need anything more */
12037     if (!AOP_INPREG(AOP(result))) {
12038         /* otherwise get a free pointer register */
12039         aop = newAsmop(0);
12040         preg = getFreePtr(ic,&aop,FALSE);
12041         pic16_emitcode("mov","%s,%s",
12042                 preg->name,
12043                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12044         rname = preg->name ;
12045     } else
12046         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12047     
12048     pic16_freeAsmop(result,NULL,ic,TRUE);
12049     pic16_aopOp (right,ic,FALSE);
12050
12051     /* if bitfield then unpack the bits */
12052     if (IS_BITFIELD(retype)) 
12053         genPackBits (retype,result,right,rname,PPOINTER);
12054     else {
12055         /* we have can just get the values */
12056         int size = AOP_SIZE(right);
12057         int offset = 0 ;        
12058         
12059         while (size--) {
12060             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12061             
12062             MOVA(l);
12063             pic16_emitcode("movx","@%s,a",rname);
12064
12065             if (size)
12066                 pic16_emitcode("inc","%s",rname);
12067
12068             offset++;
12069         }
12070     }
12071     
12072     /* now some housekeeping stuff */
12073     if (aop) {
12074         /* we had to allocate for this iCode */
12075         pic16_freeAsmop(NULL,aop,ic,TRUE);
12076     } else { 
12077         /* we did not allocate which means left
12078            already in a pointer register, then
12079            if size > 0 && this could be used again
12080            we have to point it back to where it 
12081            belongs */
12082         if (AOP_SIZE(right) > 1 &&
12083             !OP_SYMBOL(result)->remat &&
12084             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12085               ic->depth )) {
12086             int size = AOP_SIZE(right) - 1;
12087             while (size--)
12088                 pic16_emitcode("dec","%s",rname);
12089         }
12090     }
12091
12092     /* done */
12093     pic16_freeAsmop(right,NULL,ic,TRUE);
12094     
12095         
12096 }
12097
12098 #if 0
12099 /* This code is not adjusted to PIC16 and fails utterly...
12100  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12101
12102 /*-----------------------------------------------------------------*/
12103 /* genFarPointerSet - set value from far space                     */
12104 /*-----------------------------------------------------------------*/
12105 static void genFarPointerSet (operand *right,
12106                               operand *result, iCode *ic)
12107 {
12108     int size, offset ;
12109     sym_link *retype = getSpec(operandType(right));
12110
12111     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12112     pic16_aopOp(result,ic,FALSE);
12113
12114     /* if the operand is already in dptr 
12115     then we do nothing else we move the value to dptr */
12116     if (AOP_TYPE(result) != AOP_STR) {
12117         /* if this is remateriazable */
12118         if (AOP_TYPE(result) == AOP_IMMD)
12119             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12120         else { /* we need to get it byte by byte */
12121             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12122             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12123             if (options.model == MODEL_FLAT24)
12124             {
12125                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12126             }
12127         }
12128     }
12129     /* so dptr know contains the address */
12130     pic16_freeAsmop(result,NULL,ic,TRUE);
12131     pic16_aopOp(right,ic,FALSE);
12132
12133     /* if bit then unpack */
12134     if (IS_BITFIELD(retype)) 
12135         genPackBits(retype,result,right,"dptr",FPOINTER);
12136     else {
12137         size = AOP_SIZE(right);
12138         offset = 0 ;
12139
12140         while (size--) {
12141             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12142             MOVA(l);
12143             pic16_emitcode("movx","@dptr,a");
12144             if (size)
12145                 pic16_emitcode("inc","dptr");
12146         }
12147     }
12148
12149     pic16_freeAsmop(right,NULL,ic,TRUE);
12150 }
12151 #endif
12152
12153 /*-----------------------------------------------------------------*/
12154 /* genGenPointerSet - set value from generic pointer space         */
12155 /*-----------------------------------------------------------------*/
12156 #if 0
12157 static void genGenPointerSet (operand *right,
12158                               operand *result, iCode *ic)
12159 {
12160         int i, size, offset, lit;
12161         sym_link *retype = getSpec(operandType(right));
12162
12163         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12164
12165         pic16_aopOp(result,ic,FALSE);
12166         pic16_aopOp(right,ic,FALSE);
12167         size = AOP_SIZE(right);
12168         offset = 0;
12169
12170         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12171
12172         /* if the operand is already in dptr 
12173                 then we do nothing else we move the value to dptr */
12174         if (AOP_TYPE(result) != AOP_STR) {
12175                 /* if this is remateriazable */
12176                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12177                 // WARNING: anythig until "else" is untested!
12178                 if (AOP_TYPE(result) == AOP_IMMD) {
12179                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12180                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12181                         // load FSR0 from immediate
12182                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12183                         offset = 0;
12184                         while(size--) {
12185                                 if(size) {
12186                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12187                                 } else {
12188                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12189                                 }
12190                                 offset++;
12191                         }
12192                         goto release;
12193                 }
12194                 else { /* we need to get it byte by byte */
12195                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12196                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12197
12198                         // set up FSR0 with address of result
12199                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12200                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12201
12202                         /* hack hack! see if this the FSR. If so don't load W */
12203                         if(AOP_TYPE(right) != AOP_ACC) {
12204
12205                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12206
12207                                 if(AOP_TYPE(right) == AOP_LIT)
12208                                 {
12209                                         // copy literal
12210                                         // note: pic16_popGet handles sign extension
12211                                         for(i=0;i<size;i++) {
12212                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12213                                                 if(i < size-1)
12214                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12215                                                 else
12216                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12217                                         }
12218                                 } else {
12219                                         // copy regs
12220
12221                                         for(i=0;i<size;i++) {
12222                                                 if(i < size-1)
12223                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12224                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12225                                                 else
12226                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12227                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12228                                         }
12229                                 }
12230                                 goto release;
12231                         } 
12232                         // right = ACC
12233                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12234                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12235                         goto release;
12236         } // if (AOP_TYPE(result) != AOP_IMMD)
12237
12238         } // if (AOP_TYPE(result) != AOP_STR)
12239         /* so dptr know contains the address */
12240
12241
12242         /* if bit then unpack */
12243         if (IS_BITFIELD(retype)) 
12244                 genPackBits(retype,result,right,"dptr",GPOINTER);
12245         else {
12246                 size = AOP_SIZE(right);
12247                 offset = 0 ;
12248
12249                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12250
12251                 // set up FSR0 with address of result
12252                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12253                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12254         
12255                 while (size--) {
12256                         if (AOP_TYPE(right) == AOP_LIT) {
12257                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12258                                 if (size) {
12259                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12260                                 } else {
12261                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12262                                 }
12263                         } else { // no literal
12264                                 if(size) {
12265                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12266                                 } else {
12267                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12268                                 }
12269                         }
12270                         offset++;
12271                 }
12272         }
12273
12274         release:
12275         pic16_freeAsmop(right,NULL,ic,TRUE);
12276         pic16_freeAsmop(result,NULL,ic,TRUE);
12277 }
12278 #endif
12279
12280 static void genGenPointerSet (operand *right,
12281                               operand *result, iCode *ic)
12282 {
12283   int size;
12284   sym_link *retype = getSpec(operandType(result));
12285
12286     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12287
12288     pic16_aopOp(result,ic,FALSE);
12289     pic16_aopOp(right,ic,FALSE);
12290     size = AOP_SIZE(right);
12291
12292     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12293
12294
12295     /* if bit then unpack */
12296     if (IS_BITFIELD(retype)) {
12297 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12298       genPackBits(retype,result,right,"dptr",GPOINTER);
12299       goto release;
12300     }
12301
12302     size = AOP_SIZE(right);
12303
12304     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12305
12306
12307     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12308
12309     /* value of right+0 is placed on stack, which will be retrieved
12310      * by the support function thus restoring the stack. The important
12311      * thing is that there is no need to manually restore stack pointer
12312      * here */
12313     pushaop(AOP(right), 0);
12314 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12315     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12316     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12317     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12318     
12319     /* load address to write to in WREG:FSR0H:FSR0L */
12320     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12321                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12322     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12323                                 pic16_popCopyReg(&pic16_pc_prodl)));
12324     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12325     
12326     pic16_callGenericPointerRW(1, size);
12327
12328 release:
12329     pic16_freeAsmop(right,NULL,ic,TRUE);
12330     pic16_freeAsmop(result,NULL,ic,TRUE);
12331 }
12332
12333 /*-----------------------------------------------------------------*/
12334 /* genPointerSet - stores the value into a pointer location        */
12335 /*-----------------------------------------------------------------*/
12336 static void genPointerSet (iCode *ic)
12337 {    
12338   operand *right, *result ;
12339   sym_link *type, *etype;
12340   int p_type;
12341
12342     FENTRY;
12343
12344     right = IC_RIGHT(ic);
12345     result = IC_RESULT(ic) ;
12346
12347     /* depending on the type of pointer we need to
12348     move it to the correct pointer register */
12349     type = operandType(result);
12350     etype = getSpec(type);
12351     
12352     /* if left is of type of pointer then it is simple */
12353     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12354         p_type = DCL_TYPE(type);
12355     }
12356     else {
12357         /* we have to go by the storage class */
12358         p_type = PTR_TYPE(SPEC_OCLS(etype));
12359
12360 /*      if (SPEC_OCLS(etype)->codesp ) { */
12361 /*          p_type = CPOINTER ;  */
12362 /*      } */
12363 /*      else */
12364 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12365 /*              p_type = FPOINTER ; */
12366 /*          else */
12367 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12368 /*                  p_type = PPOINTER ; */
12369 /*              else */
12370 /*                  if (SPEC_OCLS(etype) == idata ) */
12371 /*                      p_type = IPOINTER ; */
12372 /*                  else */
12373 /*                      p_type = POINTER ; */
12374     }
12375
12376     /* now that we have the pointer type we assign
12377     the pointer values */
12378     switch (p_type) {
12379       case POINTER:
12380       case FPOINTER:
12381       case IPOINTER:
12382         genNearPointerSet (right,result,ic);
12383         break;
12384
12385       case PPOINTER:
12386         genPagedPointerSet (right,result,ic);
12387         break;
12388
12389 #if 0
12390       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12391       case FPOINTER:
12392         genFarPointerSet (right,result,ic);
12393         break;
12394 #endif
12395         
12396       case GPOINTER:
12397         genGenPointerSet (right,result,ic);
12398         break;
12399
12400       default:
12401         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12402           "genPointerSet: illegal pointer type");
12403     }
12404 }
12405
12406 /*-----------------------------------------------------------------*/
12407 /* genIfx - generate code for Ifx statement                        */
12408 /*-----------------------------------------------------------------*/
12409 static void genIfx (iCode *ic, iCode *popIc)
12410 {
12411   operand *cond = IC_COND(ic);
12412   int isbit =0;
12413
12414     FENTRY;
12415
12416     pic16_aopOp(cond,ic,FALSE);
12417
12418     /* get the value into acc */
12419     if (AOP_TYPE(cond) != AOP_CRY)
12420       pic16_toBoolean(cond);
12421     else
12422       isbit = 1;
12423     /* the result is now in the accumulator */
12424     pic16_freeAsmop(cond,NULL,ic,TRUE);
12425
12426     /* if there was something to be popped then do it */
12427     if (popIc)
12428       genIpop(popIc);
12429
12430     /* if the condition is  a bit variable */
12431     if (isbit && IS_ITEMP(cond) && 
12432         SPIL_LOC(cond)) {
12433       genIfxJump(ic,"c");
12434       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12435     } else {
12436       if (isbit && !IS_ITEMP(cond))
12437         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12438         else
12439         genIfxJump(ic,"a");
12440     }
12441     ic->generated = 1;
12442 }
12443
12444 /*-----------------------------------------------------------------*/
12445 /* genAddrOf - generates code for address of                       */
12446 /*-----------------------------------------------------------------*/
12447 static void genAddrOf (iCode *ic)
12448 {
12449   operand *result, *left;
12450   int size;
12451   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12452   pCodeOp *pcop0, *pcop1, *pcop2;
12453
12454     FENTRY;
12455
12456     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12457
12458     sym = OP_SYMBOL( IC_LEFT(ic) );
12459     
12460     if(sym->onStack) {
12461       /* get address of symbol on stack */
12462       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12463 #if 0
12464       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12465                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12466 #endif
12467
12468       // operands on stack are accessible via "FSR2 + index" with index
12469       // starting at 2 for arguments and growing from 0 downwards for
12470       // local variables (index == 0 is not assigned so we add one here)
12471       {
12472         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12473
12474           if (soffs <= 0) {
12475             assert (soffs < 0);
12476             soffs++;
12477           } // if
12478
12479           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12480           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12481           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12482           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12483           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12484           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12485           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12486       }
12487
12488       goto release;
12489     }
12490         
12491 //      if(pic16_debug_verbose) {
12492 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12493 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12494 //      }
12495         
12496     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12497     size = AOP_SIZE(IC_RESULT(ic));
12498
12499     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12500     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12501     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12502         
12503     if (size == 3) {
12504       pic16_emitpcode(POC_MOVLW, pcop0);
12505       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12506       pic16_emitpcode(POC_MOVLW, pcop1);
12507       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12508       pic16_emitpcode(POC_MOVLW, pcop2);
12509       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12510     } else
12511     if (size == 2) {
12512       pic16_emitpcode(POC_MOVLW, pcop0);
12513       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12514       pic16_emitpcode(POC_MOVLW, pcop1);
12515     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12516     } else {
12517       pic16_emitpcode(POC_MOVLW, pcop0);
12518       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12519     }
12520
12521     pic16_freeAsmop(left, NULL, ic, FALSE);
12522 release:
12523     pic16_freeAsmop(result,NULL,ic,TRUE);
12524 }
12525
12526
12527 #if 0
12528 /*-----------------------------------------------------------------*/
12529 /* genFarFarAssign - assignment when both are in far space         */
12530 /*-----------------------------------------------------------------*/
12531 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12532 {
12533     int size = AOP_SIZE(right);
12534     int offset = 0;
12535     char *l ;
12536     /* first push the right side on to the stack */
12537     while (size--) {
12538         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12539         MOVA(l);
12540         pic16_emitcode ("push","acc");
12541     }
12542     
12543     pic16_freeAsmop(right,NULL,ic,FALSE);
12544     /* now assign DPTR to result */
12545     pic16_aopOp(result,ic,FALSE);
12546     size = AOP_SIZE(result);
12547     while (size--) {
12548         pic16_emitcode ("pop","acc");
12549         pic16_aopPut(AOP(result),"a",--offset);
12550     }
12551     pic16_freeAsmop(result,NULL,ic,FALSE);
12552         
12553 }
12554 #endif
12555
12556 /*-----------------------------------------------------------------*/
12557 /* genAssign - generate code for assignment                        */
12558 /*-----------------------------------------------------------------*/
12559 static void genAssign (iCode *ic)
12560 {
12561   operand *result, *right;
12562   sym_link *restype, *rtype;
12563   int size, offset,know_W;
12564   unsigned long lit = 0L;
12565
12566     result = IC_RESULT(ic);
12567     right  = IC_RIGHT(ic) ;
12568
12569     FENTRY;
12570   
12571     /* if they are the same */
12572     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12573       return ;
12574
12575     /* reversed order operands are aopOp'ed so that result operand
12576      * is effective in case right is a stack symbol. This maneauver
12577      * allows to use the _G.resDirect flag later */
12578      pic16_aopOp(result,ic,TRUE);
12579     pic16_aopOp(right,ic,FALSE);
12580
12581     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12582
12583     /* if they are the same registers */
12584     if (pic16_sameRegs(AOP(right),AOP(result)))
12585       goto release;
12586
12587     /* if the result is a bit */
12588     if (AOP_TYPE(result) == AOP_CRY) {
12589       /* if the right size is a literal then
12590          we know what the value is */
12591       if (AOP_TYPE(right) == AOP_LIT) {
12592           
12593         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12594             pic16_popGet(AOP(result),0));
12595
12596         if (((int) operandLitValue(right))) 
12597           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12598               AOP(result)->aopu.aop_dir,
12599               AOP(result)->aopu.aop_dir);
12600         else
12601           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12602               AOP(result)->aopu.aop_dir,
12603               AOP(result)->aopu.aop_dir);
12604         
12605         goto release;
12606       }
12607
12608       /* the right is also a bit variable */
12609       if (AOP_TYPE(right) == AOP_CRY) {
12610         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12611         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12612         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12613
12614         goto release ;
12615       }
12616
12617       /* we need to or */
12618       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12619       pic16_toBoolean(right);
12620       emitSKPZ;
12621       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12622       //pic16_aopPut(AOP(result),"a",0);
12623       goto release ;
12624     }
12625
12626     /* bit variables done */
12627     /* general case */
12628     size = AOP_SIZE(result);
12629     offset = 0 ;
12630
12631   /* bit variables done */
12632   /* general case */
12633   size = AOP_SIZE(result);
12634   restype = operandType(result);
12635   rtype = operandType(right);
12636   offset = 0 ;
12637
12638   if(AOP_TYPE(right) == AOP_LIT) {
12639     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12640     {
12641       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12642
12643       /* patch tag for literals that are cast to pointers */
12644       if (IS_CODEPTR(restype)) {
12645         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12646         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12647       } else {
12648         if (IS_GENPTR(restype))
12649         {
12650           if (IS_CODEPTR(rtype)) {
12651             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12652             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12653           } else if (PIC_IS_DATA_PTR(rtype)) {
12654             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12655             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12656           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12657             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12658           } else if (IS_PTR(rtype)) {
12659             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12660             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12661           }
12662         }
12663       }
12664     } else {
12665       union {
12666         unsigned long lit_int;
12667         float lit_float;
12668       } info;
12669
12670
12671       if(IS_FIXED16X16(operandType(right))) {
12672         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12673       } else {
12674         /* take care if literal is a float */
12675         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12676         lit = info.lit_int;
12677       }
12678     }
12679   }
12680
12681 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12682 //                      sizeof(unsigned long int), sizeof(float));
12683
12684
12685     if (AOP_TYPE(right) == AOP_REG) {
12686       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12687       while (size--) {
12688         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12689       } // while
12690       goto release;
12691     }
12692
12693     /* when do we have to read the program memory?
12694      * - if right itself is a symbol in code space
12695      *   (we don't care what it points to if it's a pointer)
12696      * - AND right is not a function (we would want its address)
12697      */
12698     if(AOP_TYPE(right) != AOP_LIT
12699       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12700       && !IS_FUNC(OP_SYM_TYPE(right))
12701       && !IS_ITEMP(right)) {
12702
12703       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12704       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12705       
12706       // set up table pointer
12707       if(is_LitOp(right)) {
12708 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12709         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12710         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12711         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12712         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12713         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12714         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12715       } else {
12716 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12717         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12718             pic16_popCopyReg(&pic16_pc_tblptrl)));
12719         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12720             pic16_popCopyReg(&pic16_pc_tblptrh)));
12721         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12722             pic16_popCopyReg(&pic16_pc_tblptru)));
12723       }
12724
12725       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12726       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12727       while(size--) {
12728         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12729         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12730             pic16_popGet(AOP(result),offset)));
12731         offset++;
12732       }
12733
12734       /* FIXME: for pointers we need to extend differently (according
12735        * to pointer type DATA/CODE/EEPROM/... :*/
12736       size = getSize(OP_SYM_TYPE(right));
12737       if(AOP_SIZE(result) > size) {
12738         size = AOP_SIZE(result) - size;
12739         while(size--) {
12740           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12741           offset++;
12742         }
12743       }
12744       goto release;
12745     }
12746
12747 #if 0
12748     /* VR - What is this?! */
12749     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12750       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12751       
12752       if(aopIdx(AOP(result),0) == 4) {
12753         /* this is a workaround to save value of right into wreg too,
12754          * value of wreg is going to be used later */
12755         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12756         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12757         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12758         goto release;
12759       } else
12760 //      assert(0);
12761       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12762     }
12763 #endif
12764
12765     size = AOP_SIZE(right);
12766     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12767     know_W=-1;
12768     while (size--) {
12769       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12770       if(AOP_TYPE(right) == AOP_LIT) {
12771         if(lit&0xff) {
12772           if(know_W != (lit&0xff))
12773             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12774           know_W = lit&0xff;
12775           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12776         } else
12777           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12778
12779         lit >>= 8;
12780
12781       } else if (AOP_TYPE(right) == AOP_CRY) {
12782         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12783         if(offset == 0) {
12784           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12785           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12786           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12787         }
12788       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12789         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12790         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12791       } else {
12792         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12793
12794         if(!_G.resDirect) {                                             /* use this aopForSym feature */
12795           if(AOP_TYPE(result) == AOP_ACC) {
12796             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12797           } else
12798             if(AOP_TYPE(right) == AOP_ACC) {
12799               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12800             } else {
12801               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12802             }
12803         }
12804       }
12805
12806       offset++;
12807     }
12808     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12809   
12810 release:
12811   pic16_freeAsmop (right,NULL,ic,FALSE);
12812   pic16_freeAsmop (result,NULL,ic,TRUE);
12813
12814
12815 /*-----------------------------------------------------------------*/
12816 /* genJumpTab - generates code for jump table                       */
12817 /*-----------------------------------------------------------------*/
12818 static void genJumpTab (iCode *ic)
12819 {
12820   symbol *jtab;
12821   char *l;
12822   pCodeOp *jt_offs;
12823   pCodeOp *jt_offs_hi;
12824   pCodeOp *jt_label;
12825
12826     FENTRY;
12827
12828     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12829     /* get the condition into accumulator */
12830     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12831     MOVA(l);
12832     /* multiply by three */
12833     pic16_emitcode("add","a,acc");
12834     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12835
12836     jtab = newiTempLabel(NULL);
12837     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12838     pic16_emitcode("jmp","@a+dptr");
12839     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12840
12841 #if 0
12842     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12843     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12844     emitSKPNC;
12845     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12846     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12847     pic16_emitpLabel(jtab->key);
12848
12849 #else
12850
12851     jt_offs = pic16_popGetTempReg(0);
12852     jt_offs_hi = pic16_popGetTempReg(1);
12853     jt_label = pic16_popGetLabel (jtab->key);
12854     //fprintf (stderr, "Creating jump table...\n");
12855
12856     // calculate offset into jump table (idx * sizeof (GOTO))
12857     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12858     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12859     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12860     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12861     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12862     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12863     pic16_emitpcode(POC_MOVWF , jt_offs);
12864
12865     // prepare PCLATx (set to first entry in jump table)
12866     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12867     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12868     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12869     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12870     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12871
12872     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12873     pic16_emitpcode(POC_ADDWF , jt_offs);
12874     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12875     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12876     emitSKPNC;
12877     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12878
12879     // release temporaries and prepare jump into table (new PCL --> WREG)
12880     pic16_emitpcode(POC_MOVFW , jt_offs);
12881     pic16_popReleaseTempReg (jt_offs_hi, 1);
12882     pic16_popReleaseTempReg (jt_offs, 0);
12883
12884     // jump into the table
12885     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12886
12887     pic16_emitpLabelFORCE(jtab->key);
12888 #endif
12889
12890     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12891 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12892
12893     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12894     /* now generate the jump labels */
12895     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12896          jtab = setNextItem(IC_JTLABELS(ic))) {
12897 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12898         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12899         
12900     }
12901     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12902
12903 }
12904
12905 /*-----------------------------------------------------------------*/
12906 /* genMixedOperation - gen code for operators between mixed types  */
12907 /*-----------------------------------------------------------------*/
12908 /*
12909   TSD - Written for the PIC port - but this unfortunately is buggy.
12910   This routine is good in that it is able to efficiently promote 
12911   types to different (larger) sizes. Unfortunately, the temporary
12912   variables that are optimized out by this routine are sometimes
12913   used in other places. So until I know how to really parse the 
12914   iCode tree, I'm going to not be using this routine :(.
12915 */
12916 static int genMixedOperation (iCode *ic)
12917 {
12918 #if 0
12919   operand *result = IC_RESULT(ic);
12920   sym_link *ctype = operandType(IC_LEFT(ic));
12921   operand *right = IC_RIGHT(ic);
12922   int ret = 0;
12923   int big,small;
12924   int offset;
12925
12926   iCode *nextic;
12927   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12928
12929   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12930
12931   nextic = ic->next;
12932   if(!nextic)
12933     return 0;
12934
12935   nextright = IC_RIGHT(nextic);
12936   nextleft  = IC_LEFT(nextic);
12937   nextresult = IC_RESULT(nextic);
12938
12939   pic16_aopOp(right,ic,FALSE);
12940   pic16_aopOp(result,ic,FALSE);
12941   pic16_aopOp(nextright,  nextic, FALSE);
12942   pic16_aopOp(nextleft,   nextic, FALSE);
12943   pic16_aopOp(nextresult, nextic, FALSE);
12944
12945   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12946
12947     operand *t = right;
12948     right = nextright;
12949     nextright = t; 
12950
12951     pic16_emitcode(";remove right +","");
12952
12953   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12954 /*
12955     operand *t = right;
12956     right = nextleft;
12957     nextleft = t; 
12958 */
12959     pic16_emitcode(";remove left +","");
12960   } else
12961     return 0;
12962
12963   big = AOP_SIZE(nextleft);
12964   small = AOP_SIZE(nextright);
12965
12966   switch(nextic->op) {
12967
12968   case '+':
12969     pic16_emitcode(";optimize a +","");
12970     /* if unsigned or not an integral type */
12971     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12972       pic16_emitcode(";add a bit to something","");
12973     } else {
12974
12975       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12976
12977       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12978         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12979         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12980       } else
12981         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12982
12983       offset = 0;
12984       while(--big) {
12985
12986         offset++;
12987
12988         if(--small) {
12989           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12990             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12991             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12992           }
12993
12994           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12995           emitSKPNC;
12996           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12997                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12998                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12999           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13000           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13001
13002         } else {
13003           pic16_emitcode("rlf","known_zero,w");
13004
13005           /*
13006             if right is signed
13007               btfsc  right,7
13008                addlw ff
13009           */
13010           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13011             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13012             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13013           } else {
13014             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13015           }
13016         }
13017       }
13018       ret = 1;
13019     }
13020   }
13021   ret = 1;
13022
13023 release:
13024   pic16_freeAsmop(right,NULL,ic,TRUE);
13025   pic16_freeAsmop(result,NULL,ic,TRUE);
13026   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13027   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13028   if(ret)
13029     nextic->generated = 1;
13030
13031   return ret;
13032 #else
13033   return 0;
13034 #endif
13035 }
13036 /*-----------------------------------------------------------------*/
13037 /* genCast - gen code for casting                                  */
13038 /*-----------------------------------------------------------------*/
13039 static void genCast (iCode *ic)
13040 {
13041   operand *result = IC_RESULT(ic);
13042   sym_link *ctype = operandType(IC_LEFT(ic));
13043   sym_link *rtype = operandType(IC_RIGHT(ic));
13044   sym_link *restype = operandType(IC_RESULT(ic));
13045   operand *right = IC_RIGHT(ic);
13046   int size, offset ;
13047
13048
13049     FENTRY;
13050
13051         /* if they are equivalent then do nothing */
13052 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13053 //              return ;
13054
13055         pic16_aopOp(result,ic,FALSE);
13056         pic16_aopOp(right,ic,FALSE) ;
13057
13058         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13059
13060
13061         /* if the result is a bit */
13062         if (AOP_TYPE(result) == AOP_CRY) {
13063         
13064                 /* if the right size is a literal then
13065                  * we know what the value is */
13066                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13067
13068                 if (AOP_TYPE(right) == AOP_LIT) {
13069                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13070                                 pic16_popGet(AOP(result),0));
13071
13072                         if (((int) operandLitValue(right))) 
13073                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13074                                         AOP(result)->aopu.aop_dir,
13075                                         AOP(result)->aopu.aop_dir);
13076                         else
13077                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13078                                         AOP(result)->aopu.aop_dir,
13079                                         AOP(result)->aopu.aop_dir);
13080                         goto release;
13081                 }
13082
13083                 /* the right is also a bit variable */
13084                 if (AOP_TYPE(right) == AOP_CRY) {
13085                         emitCLRC;
13086                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13087
13088                         pic16_emitcode("clrc","");
13089                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13090                                 AOP(right)->aopu.aop_dir,
13091                                 AOP(right)->aopu.aop_dir);
13092                         pic16_aopPut(AOP(result),"c",0);
13093                         goto release ;
13094                 }
13095
13096                 /* we need to or */
13097                 if (AOP_TYPE(right) == AOP_REG) {
13098                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13099                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13100                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13101                 }
13102                 pic16_toBoolean(right);
13103                 pic16_aopPut(AOP(result),"a",0);
13104                 goto release ;
13105         }
13106
13107         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13108           int offset = 1;
13109
13110                 size = AOP_SIZE(result);
13111
13112                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13113
13114                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13115                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13116                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13117
13118                 while (size--)
13119                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13120
13121                 goto release;
13122         }
13123
13124         if(IS_BITFIELD(getSpec(restype))
13125           && IS_BITFIELD(getSpec(rtype))) {
13126           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13127         }
13128         
13129         /* port from pic14 to cope with generic pointers */
13130         if (PIC_IS_TAGGED(restype))
13131         {
13132           operand *result = IC_RESULT(ic);
13133           //operand *left = IC_LEFT(ic);
13134           operand *right = IC_RIGHT(ic);
13135           int tag = 0xff;
13136
13137           /* copy common part */
13138           int max, size = AOP_SIZE(result);
13139           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13140           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13141
13142           max = size;
13143           while (size--)
13144           {
13145             pic16_mov2w (AOP(right), size);
13146             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13147           } // while
13148
13149           /* upcast into generic pointer type? */
13150           if (IS_GENPTR(restype)
13151               && !PIC_IS_TAGGED(rtype)
13152               && (AOP_SIZE(result) > max))
13153           {
13154             /* determine appropriate tag for right */
13155             if (PIC_IS_DATA_PTR(rtype))
13156               tag = GPTR_TAG_DATA;
13157             else if (IS_CODEPTR(rtype))
13158               tag = GPTR_TAG_CODE;
13159             else if (PIC_IS_DATA_PTR(ctype)) {
13160               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13161               tag = GPTR_TAG_DATA;
13162             } else if (IS_CODEPTR(ctype)) {
13163               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13164               tag = GPTR_TAG_CODE;
13165             } else if (IS_PTR(rtype)) {
13166               PERFORM_ONCE(weirdcast,
13167               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13168               );
13169               tag = GPTR_TAG_DATA;
13170             } else {
13171               PERFORM_ONCE(weirdcast,
13172               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13173               );
13174               tag = GPTR_TAG_DATA;
13175             }
13176
13177             assert (AOP_SIZE(result) == 3);
13178             /* zero-extend address... */
13179             for (size = max; size < AOP_SIZE(result)-1; size++)
13180               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13181             /* ...and add tag */
13182             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13183           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13184             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13185             for (size = max; size < AOP_SIZE(result)-1; size++)
13186               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13187             /* add __code tag */
13188             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13189           } else if (AOP_SIZE(result) > max) {
13190             /* extend non-pointers */
13191             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13192             pic16_addSign(result, max, 0);
13193           } // if
13194           goto release;
13195         }
13196
13197         /* if they are the same size : or less */
13198         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13199
13200                 /* if they are in the same place */
13201                 if (pic16_sameRegs(AOP(right),AOP(result)))
13202                         goto release;
13203
13204                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13205 #if 0
13206                 if (IS_PTR_CONST(rtype))
13207 #else
13208                 if (IS_CODEPTR(rtype))
13209 #endif
13210                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13211
13212 #if 0
13213                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13214 #else
13215                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13216 #endif
13217                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13218
13219 #if 0
13220                 if(AOP_TYPE(right) == AOP_IMMD) {
13221                   pCodeOp *pcop0, *pcop1, *pcop2;
13222                   symbol *sym = OP_SYMBOL( right );
13223
13224                         size = AOP_SIZE(result);
13225                         /* low */
13226                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13227                         /* high */
13228                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13229                         /* upper */
13230                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13231         
13232                         if (size == 3) {
13233                                 pic16_emitpcode(POC_MOVLW, pcop0);
13234                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13235                                 pic16_emitpcode(POC_MOVLW, pcop1);
13236                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13237                                 pic16_emitpcode(POC_MOVLW, pcop2);
13238                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13239                         } else
13240                         if (size == 2) {
13241                                 pic16_emitpcode(POC_MOVLW, pcop0);
13242                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13243                                 pic16_emitpcode(POC_MOVLW, pcop1);
13244                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13245                         } else {
13246                                 pic16_emitpcode(POC_MOVLW, pcop0);
13247                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13248                         }
13249                 } else
13250 #endif
13251                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13252                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13253                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13254
13255                         if(AOP_SIZE(result) < 2) {
13256                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13257                         } else {
13258                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13259                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13260                         }
13261                 } else {
13262                         /* if they in different places then copy */
13263                         size = AOP_SIZE(result);
13264                         offset = 0 ;
13265                         while (size--) {
13266                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13267                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13268                                 offset++;
13269                         }
13270                 }
13271                 goto release;
13272         }
13273
13274         /* if the result is of type pointer */
13275         if (IS_PTR(ctype)) {
13276           int p_type;
13277           sym_link *type = operandType(right);
13278           sym_link *etype = getSpec(type);
13279
13280                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13281
13282                 /* pointer to generic pointer */
13283                 if (IS_GENPTR(ctype)) {
13284                   char *l = zero;
13285             
13286                         if (IS_PTR(type)) 
13287                                 p_type = DCL_TYPE(type);
13288                         else {
13289                 /* we have to go by the storage class */
13290                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13291
13292 /*              if (SPEC_OCLS(etype)->codesp )  */
13293 /*                  p_type = CPOINTER ;  */
13294 /*              else */
13295 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13296 /*                      p_type = FPOINTER ; */
13297 /*                  else */
13298 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13299 /*                          p_type = PPOINTER; */
13300 /*                      else */
13301 /*                          if (SPEC_OCLS(etype) == idata ) */
13302 /*                              p_type = IPOINTER ; */
13303 /*                          else */
13304 /*                              p_type = POINTER ; */
13305             }
13306                 
13307             /* the first two bytes are known */
13308       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13309             size = GPTRSIZE - 1; 
13310             offset = 0 ;
13311             while (size--) {
13312               if(offset < AOP_SIZE(right)) {
13313                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13314                 pic16_mov2f(AOP(result), AOP(right), offset);
13315 /*
13316                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13317                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13318                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13319                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13320                 } else { 
13321                   
13322                   pic16_aopPut(AOP(result),
13323                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13324                          offset);
13325                 }
13326 */
13327               } else 
13328                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13329               offset++;
13330             }
13331             /* the last byte depending on type */
13332             switch (p_type) {
13333             case IPOINTER:
13334             case POINTER:
13335             case FPOINTER:
13336                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13337                 break;
13338
13339             case CPOINTER:
13340                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13341                 break;
13342
13343             case PPOINTER:
13344               pic16_emitcode(";BUG!? ","%d",__LINE__);
13345                 l = "#0x03";
13346                 break;
13347
13348             case GPOINTER:
13349                 if (GPTRSIZE > AOP_SIZE(right)) {
13350                   // assume __data pointer... THIS MIGHT BE WRONG!
13351                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13352                 } else {
13353                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13354                 }
13355               break;
13356               
13357             default:
13358                 /* this should never happen */
13359                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13360                        "got unknown pointer type");
13361                 exit(1);
13362             }
13363             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13364             goto release ;
13365         }
13366         
13367         
13368         assert( 0 );
13369         /* just copy the pointers */
13370         size = AOP_SIZE(result);
13371         offset = 0 ;
13372         while (size--) {
13373             pic16_aopPut(AOP(result),
13374                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13375                    offset);
13376             offset++;
13377         }
13378         goto release ;
13379     }
13380     
13381
13382
13383     /* so we now know that the size of destination is greater
13384     than the size of the source.
13385     Now, if the next iCode is an operator then we might be
13386     able to optimize the operation without performing a cast.
13387     */
13388     if(genMixedOperation(ic))
13389       goto release;
13390
13391     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13392     
13393     /* we move to result for the size of source */
13394     size = AOP_SIZE(right);
13395     offset = 0 ;
13396
13397     while (size--) {
13398       if(!_G.resDirect)
13399         pic16_mov2f(AOP(result), AOP(right), offset);
13400       offset++;
13401     }
13402
13403     /* now depending on the sign of the destination */
13404     size = AOP_SIZE(result) - AOP_SIZE(right);
13405     /* if unsigned or not an integral type */
13406     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13407       while (size--)
13408         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13409     } else {
13410       /* we need to extend the sign :( */
13411
13412       if(size == 1) {
13413         /* Save one instruction of casting char to int */
13414         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13415         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13416         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13417       } else {
13418         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13419
13420         if(offset)
13421           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13422         else
13423           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13424         
13425         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13426
13427         while (size--)
13428           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13429       }
13430     }
13431
13432 release:
13433     pic16_freeAsmop(right,NULL,ic,TRUE);
13434     pic16_freeAsmop(result,NULL,ic,TRUE);
13435
13436 }
13437
13438 /*-----------------------------------------------------------------*/
13439 /* genDjnz - generate decrement & jump if not zero instrucion      */
13440 /*-----------------------------------------------------------------*/
13441 static int genDjnz (iCode *ic, iCode *ifx)
13442 {
13443     symbol *lbl, *lbl1;
13444     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13445
13446     if (!ifx)
13447         return 0;
13448     
13449     /* if the if condition has a false label
13450        then we cannot save */
13451     if (IC_FALSE(ifx))
13452         return 0;
13453
13454     /* if the minus is not of the form 
13455        a = a - 1 */
13456     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13457         !IS_OP_LITERAL(IC_RIGHT(ic)))
13458         return 0;
13459
13460     if (operandLitValue(IC_RIGHT(ic)) != 1)
13461         return 0;
13462
13463     /* if the size of this greater than one then no
13464        saving */
13465     if (getSize(operandType(IC_RESULT(ic))) > 1)
13466         return 0;
13467
13468     /* otherwise we can save BIG */
13469     lbl = newiTempLabel(NULL);
13470     lbl1= newiTempLabel(NULL);
13471
13472     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13473     
13474     if (IS_AOP_PREG(IC_RESULT(ic))) {
13475         pic16_emitcode("dec","%s",
13476                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13477         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13478         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13479     } else {    
13480
13481
13482       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13483       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13484
13485       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13486       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13487
13488     }
13489     
13490     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13491     ifx->generated = 1;
13492     return 1;
13493 }
13494
13495 /*-----------------------------------------------------------------*/
13496 /* genReceive - generate code for a receive iCode                  */
13497 /*-----------------------------------------------------------------*/
13498 static void genReceive (iCode *ic)
13499 {    
13500
13501   FENTRY;
13502
13503 #if 0
13504   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13505         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13506 #endif
13507 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13508
13509   if (isOperandInFarSpace(IC_RESULT(ic))
13510       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13511           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13512
13513     int size = getSize(operandType(IC_RESULT(ic)));
13514     int offset =  pic16_fReturnSizePic - size;
13515
13516       assert( 0 );
13517       while (size--) {
13518         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13519                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13520                       offset++;
13521         }
13522
13523       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13524
13525       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13526       size = AOP_SIZE(IC_RESULT(ic));
13527       offset = 0;
13528       while (size--) {
13529         pic16_emitcode ("pop","acc");
13530         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13531       }
13532   } else {
13533     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13534     _G.accInUse++;
13535     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13536     _G.accInUse--;
13537
13538     /* set pseudo stack pointer to where it should be - dw*/
13539     GpsuedoStkPtr = ic->parmBytes;
13540
13541     /* setting GpsuedoStkPtr has side effects here: */
13542     /* FIXME: What's the correct size of the return(ed) value?
13543      *        For now, assuming '4' as before... */
13544     assignResultValue(IC_RESULT(ic), 4, 0);
13545   }
13546
13547   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13548 }
13549
13550 /*-----------------------------------------------------------------*/
13551 /* genDummyRead - generate code for dummy read of volatiles        */
13552 /*-----------------------------------------------------------------*/
13553 static void
13554 genDummyRead (iCode * ic)
13555 {
13556   operand *op;
13557   int i;
13558
13559   op = IC_RIGHT(ic);
13560   if (op && IS_SYMOP(op)) {
13561     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13562       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13563       return;
13564     }
13565     pic16_aopOp (op, ic, FALSE);
13566     for (i=0; i < AOP_SIZE(op); i++) {
13567       // may need to protect this from the peepholer -- this is not nice but works...
13568       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13569       pic16_mov2w (AOP(op),i);
13570       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13571     } // for i
13572     pic16_freeAsmop (op, NULL, ic, TRUE);
13573   } else if (op) {
13574     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13575   } // if
13576 }
13577
13578 /*-----------------------------------------------------------------*/
13579 /* genpic16Code - generate code for pic16 based controllers        */
13580 /*-----------------------------------------------------------------*/
13581 /*
13582  * At this point, ralloc.c has gone through the iCode and attempted
13583  * to optimize in a way suitable for a PIC. Now we've got to generate
13584  * PIC instructions that correspond to the iCode.
13585  *
13586  * Once the instructions are generated, we'll pass through both the
13587  * peep hole optimizer and the pCode optimizer.
13588  *-----------------------------------------------------------------*/
13589
13590 void genpic16Code (iCode *lic)
13591 {
13592   iCode *ic;
13593   int cln = 0;
13594
13595     lineHead = lineCurr = NULL;
13596
13597     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13598     pic16_addpBlock(pb);
13599
13600 #if 0
13601     /* if debug information required */
13602     if (options.debug && currFunc) {
13603       if (currFunc) {
13604         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13605       }
13606     }
13607 #endif
13608
13609     for (ic = lic ; ic ; ic = ic->next ) {
13610
13611       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13612       if ( cln != ic->lineno ) {
13613         if ( options.debug ) {
13614           debugFile->writeCLine (ic);
13615         }
13616         
13617         if(!options.noCcodeInAsm) {
13618           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13619               printCLine(ic->filename, ic->lineno)));
13620         }
13621
13622         cln = ic->lineno ;
13623       }
13624         
13625       if(options.iCodeInAsm) {
13626         char *l;
13627
13628           /* insert here code to print iCode as comment */
13629           l = Safe_strdup(printILine(ic));
13630           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13631       }
13632
13633       /* if the result is marked as
13634        * spilt and rematerializable or code for
13635        * this has already been generated then
13636        * do nothing */
13637       if (resultRemat(ic) || ic->generated ) 
13638         continue ;
13639         
13640       /* depending on the operation */
13641       switch (ic->op) {
13642         case '!' :
13643           pic16_genNot(ic);
13644           break;
13645             
13646         case '~' :
13647           pic16_genCpl(ic);
13648           break;
13649             
13650         case UNARYMINUS:
13651           genUminus (ic);
13652           break;
13653             
13654         case IPUSH:
13655           genIpush (ic);
13656           break;
13657             
13658         case IPOP:
13659           /* IPOP happens only when trying to restore a 
13660            * spilt live range, if there is an ifx statement
13661            * following this pop then the if statement might
13662            * be using some of the registers being popped which
13663            * would destroy the contents of the register so
13664            * we need to check for this condition and handle it */
13665            if (ic->next
13666              && ic->next->op == IFX
13667              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13668                genIfx (ic->next,ic);
13669           else
13670             genIpop (ic);
13671           break; 
13672             
13673         case CALL:
13674           genCall (ic);
13675           break;
13676             
13677         case PCALL:
13678           genPcall (ic);
13679           break;
13680             
13681         case FUNCTION:
13682           genFunction (ic);
13683           break;
13684             
13685         case ENDFUNCTION:
13686           genEndFunction (ic);
13687           break;
13688             
13689         case RETURN:
13690           genRet (ic);
13691           break;
13692             
13693         case LABEL:
13694           genLabel (ic);
13695           break;
13696             
13697         case GOTO:
13698           genGoto (ic);
13699           break;
13700             
13701         case '+' :
13702           pic16_genPlus (ic) ;
13703           break;
13704             
13705         case '-' :
13706           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13707             pic16_genMinus (ic);
13708           break;
13709
13710         case '*' :
13711           genMult (ic);
13712           break;
13713             
13714         case '/' :
13715           genDiv (ic) ;
13716           break;
13717             
13718         case '%' :
13719           genMod (ic);
13720           break;
13721             
13722         case '>' :
13723           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13724           break;
13725             
13726         case '<' :
13727           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13728           break;
13729             
13730         case LE_OP:
13731         case GE_OP:
13732         case NE_OP:
13733           /* note these two are xlated by algebraic equivalence
13734            * during parsing SDCC.y */
13735           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13736             "got '>=' or '<=' shouldn't have come here");
13737           break;
13738
13739         case EQ_OP:
13740           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13741           break;            
13742             
13743         case AND_OP:
13744           genAndOp (ic);
13745           break;
13746             
13747         case OR_OP:
13748           genOrOp (ic);
13749           break;
13750             
13751         case '^' :
13752           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13753           break;
13754             
13755         case '|' :
13756           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13757           break;
13758             
13759         case BITWISEAND:
13760           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13761           break;
13762             
13763         case INLINEASM:
13764           genInline (ic);
13765           break;
13766             
13767         case RRC:
13768           genRRC (ic);
13769           break;
13770             
13771         case RLC:
13772           genRLC (ic);
13773           break;
13774             
13775         case GETHBIT:
13776           genGetHbit (ic);
13777           break;
13778             
13779         case LEFT_OP:
13780           genLeftShift (ic);
13781           break;
13782             
13783         case RIGHT_OP:
13784           genRightShift (ic);
13785           break;
13786             
13787         case GET_VALUE_AT_ADDRESS:
13788           genPointerGet(ic);
13789           break;
13790             
13791         case '=' :
13792           if (POINTER_SET(ic))
13793             genPointerSet(ic);
13794           else
13795             genAssign(ic);
13796           break;
13797             
13798         case IFX:
13799           genIfx (ic,NULL);
13800           break;
13801             
13802         case ADDRESS_OF:
13803           genAddrOf (ic);
13804           break;
13805             
13806         case JUMPTABLE:
13807           genJumpTab (ic);
13808           break;
13809             
13810         case CAST:
13811           genCast (ic);
13812           break;
13813             
13814         case RECEIVE:
13815           genReceive(ic);
13816           break;
13817             
13818         case SEND:
13819           addSet(&_G.sendSet,ic);
13820           break;
13821
13822         case DUMMY_READ_VOLATILE:
13823           genDummyRead (ic);
13824           break;
13825
13826         default :
13827           ic = ic;
13828       }
13829     }
13830
13831
13832     /* now we are ready to call the
13833        peep hole optimizer */
13834     if (!options.nopeep)
13835       peepHole (&lineHead);
13836
13837     /* now do the actual printing */
13838     printLine (lineHead, codeOutFile);
13839
13840 #ifdef PCODE_DEBUG
13841     DFPRINTF((stderr,"printing pBlock\n\n"));
13842     pic16_printpBlock(stdout,pb);
13843 #endif
13844
13845     return;
13846 }
13847