* src/pic/glue.h,src/pic16/glue.h: added prototypes
[fw/sdcc] / src / pic16 / gen.c
1  /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9              -  Vangelis Rokas <vrokas AT users.sourceforge.net> (2003-2006)
10   Bug Fixes  -  Raphael Neider <rneider AT web.de> (2004,2005)
11   
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16   
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21   
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25   
26   In other words, you are welcome to use, share and improve this program.
27   You are forbidden to forbid anyone else to use, share and improve
28   what you give them.   Help stamp out software-hoarding!
29   
30   Notes:
31   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
32                 Made everything static
33 -------------------------------------------------------------------------*/
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include "SDCCglobl.h"
40 #include "newalloc.h"
41
42 #include "common.h"
43 #include "SDCCpeeph.h"
44 #include "ralloc.h"
45 #include "pcode.h"
46 #include "gen.h"
47 #include "genutils.h"
48 #include "device.h"
49 #include "main.h"
50 #include "glue.h"
51
52 /* Set the following to 1 to enable the slower/bigger
53  * but more robust generic shifting routine (which also
54  * operates correctly with negative shift values). */
55 #define USE_GENERIC_SIGNED_SHIFT 1
56
57 /* Set the following to 1 to enable the new
58  * stripped down genCmp version.
59  * This version should be easier to understand,
60  * more reliable and (sigh) slighly slower. */
61 #define USE_SIMPLE_GENCMP 1
62
63 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
64 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
66 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
67 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
68
69 /* If you change these, you also have to update the library files
70  * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
71 #define GPTR_TAG_DATA   0x80
72 #define GPTR_TAG_EEPROM 0x40
73 #define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
74
75 /* Wrapper to execute `code' at most once. */
76 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
77
78 void pic16_genMult8X8_n (operand *, operand *,operand *);
79 #if 0
80 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
81 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
82 void pic16_genMult16X16_16(operand *, operand *, operand *);
83 void pic16_genMult32X32_32(operand *, operand *, operand *);
84 #endif
85 pCode *pic16_AssembleLine(char *line, int peeps);
86 extern void pic16_printpBlock(FILE *of, pBlock *pb);
87 static asmop *newAsmop (short type);
88 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
89 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
90 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
91 static pCodeOp *pic16_popRegFromIdx(int rIdx);
92
93 //static int aopIdx (asmop *aop, int offset);
94
95 int pic16_labelOffset=0;
96 extern int pic16_debug_verbose;
97 #if !(USE_GENERIC_SIGNED_SHIFT)
98 static int optimized_for_speed = 0;
99 #endif
100 /*
101   hack hack
102
103 */
104
105 extern set *externs;
106
107 /* max_key keeps track of the largest label number used in 
108    a function. This is then used to adjust the label offset
109    for the next function.
110 */
111 static int max_key=0;
112 static int GpsuedoStkPtr=0;
113
114 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
115
116 const char *pic16_AopType(short type);
117 static iCode *ifxForOp ( operand *op, iCode *ic );
118
119 void pic16_pushpCodeOp(pCodeOp *pcop);
120 void pic16_poppCodeOp(pCodeOp *pcop);
121
122 static bool is_LitOp(operand *op);
123 static bool is_LitAOp(asmop *aop);
124
125
126 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
127
128 /* set the following macro to 1 to enable passing the
129  * first byte of functions parameters via WREG */
130 #define USE_WREG_IN_FUNC_PARAMS 0
131
132
133 /* this is the down and dirty file with all kinds of 
134    kludgy & hacky stuff. This is what it is all about
135    CODE GENERATION for a specific MCU . some of the
136    routines may be reusable, will have to see */
137
138 static char *zero = "#0x00";
139 static char *one  = "#0x01";
140 //static char *spname = "sp";
141
142
143 /*
144  * Function return value policy (MSB-->LSB):
145  *  8 bits      -> WREG
146  * 16 bits      -> PRODL:WREG
147  * 24 bits      -> PRODH:PRODL:WREG
148  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
149  * >32 bits     -> on stack, and FSR0 points to the beginning
150  *
151  */
152  
153
154 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
155 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
156 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
157 static char **fReturn = fReturnpic16;
158
159 static char *accUse[] = {"WREG"};
160
161 //static short rbank = -1;
162
163 static struct {
164     short r0Pushed;
165     short r1Pushed;
166     short fsr0Pushed;
167     short accInUse;
168     short inLine;
169     short debugLine;
170     short nRegsSaved;
171     short ipushRegs;
172     set *sendSet;
173     set *stackRegSet;
174     int usefastretfie;
175     bitVect *fregsUsed;                 /* registers used in function */
176     bitVect *sregsAlloc;
177     set *sregsAllocSet;                 /* registers used to store stack variables */
178     int stack_lat;                      /* stack offset latency */
179     int resDirect;
180     int useWreg;                        /* flag when WREG is used to pass function parameter */
181 } _G;
182
183 extern int pic16_ptrRegReq ;
184 extern int pic16_nRegs;
185 extern FILE *codeOutFile;
186 //static void saverbank (int, iCode *,bool);
187
188 static lineNode *lineHead = NULL;
189 static lineNode *lineCurr = NULL;
190
191 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
192 0xE0, 0xC0, 0x80, 0x00};
193 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
194 0x07, 0x03, 0x01, 0x00};
195
196 static  pBlock *pb;
197
198 /*-----------------------------------------------------------------*/
199 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
200 /*                 exponent of 2 is returned, otherwise -1 is      */
201 /*                 returned.                                       */
202 /* note that this is similar to the function `powof2' in SDCCsymt  */
203 /* if(n == 2^y)                                                    */
204 /*   return y;                                                     */
205 /* return -1;                                                      */
206 /*-----------------------------------------------------------------*/
207 int pic16_my_powof2 (unsigned long num)
208 {
209   if(num) {
210     if( (num & (num-1)) == 0) {
211       int nshifts = -1;
212       while(num) {
213         num>>=1;
214         nshifts++;
215       }
216       return nshifts;
217     }
218   }
219
220   return -1;
221 }
222
223 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
224 {
225   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
226                        line_no,
227                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
228                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
229                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
230                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
231                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
232                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
233                        ((result) ? AOP_SIZE(result) : 0));
234 }
235
236 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
237 {
238
239   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
240                        line_no,
241                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
242                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
243                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
244                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
245                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
246                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
247
248 }
249
250 void pic16_emitpcomment (char *fmt, ...)
251 {
252     va_list ap;
253     char lb[INITIAL_INLINEASM];  
254     unsigned char *lbp = (unsigned char *)lb;
255
256     va_start(ap,fmt);   
257
258     lb[0] = ';';
259     vsprintf(lb+1,fmt,ap);
260
261     while (isspace(*lbp)) lbp++;
262
263     if (lbp && *lbp) 
264         lineCurr = (lineCurr ?
265                     connectLine(lineCurr,newLineNode(lb)) :
266                     (lineHead = newLineNode(lb)));
267     lineCurr->isInline = _G.inLine;
268     lineCurr->isDebug  = _G.debugLine;
269
270     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
271     va_end(ap);
272
273 //      fprintf(stderr, "%s\n", lb);
274 }
275
276 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
277 {
278     va_list ap;
279     char lb[INITIAL_INLINEASM];  
280     unsigned char *lbp = (unsigned char *)lb;
281
282     if(!pic16_debug_verbose)
283       return;
284
285     va_start(ap,fmt);   
286
287     if (inst && *inst) {
288         if (fmt && *fmt)
289             sprintf(lb,"%s\t",inst);
290         else
291             sprintf(lb,"%s",inst);
292         vsprintf(lb+(strlen(lb)),fmt,ap);
293     }  else
294         vsprintf(lb,fmt,ap);
295
296     while (isspace(*lbp)) lbp++;
297
298     if (lbp && *lbp) 
299         lineCurr = (lineCurr ?
300                     connectLine(lineCurr,newLineNode(lb)) :
301                     (lineHead = newLineNode(lb)));
302     lineCurr->isInline = _G.inLine;
303     lineCurr->isDebug  = _G.debugLine;
304
305     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
306     va_end(ap);
307
308 //      fprintf(stderr, "%s\n", lb);
309 }
310
311
312
313 void pic16_emitpLabel(int key)
314 {
315   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
316 }
317
318 void pic16_emitpLabelFORCE(int key)
319 {
320   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
321 }
322
323 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
324  * NEVER call pic16_emitpcode_real directly, please... */
325 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
326 {
327
328   if(pcop)
329     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
330   else
331     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
332 }
333
334 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
335 {
336   if(pcop)
337     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
338   else
339     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
340 }
341   
342 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
343 {
344
345   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
346
347 }
348
349
350 #if 1
351 #define pic16_emitcode  DEBUGpic16_emitcode
352 #else
353 /*-----------------------------------------------------------------*/
354 /* pic16_emitcode - writes the code into a file : for now it is simple    */
355 /*-----------------------------------------------------------------*/
356 void pic16_emitcode (char *inst,char *fmt, ...)
357 {
358     va_list ap;
359     char lb[INITIAL_INLINEASM];  
360     unsigned char *lbp = lb;
361
362     va_start(ap,fmt);   
363
364     if (inst && *inst) {
365         if (fmt && *fmt)
366             sprintf(lb,"%s\t",inst);
367         else
368             sprintf(lb,"%s",inst);
369         vsprintf(lb+(strlen(lb)),fmt,ap);
370     }  else
371         vsprintf(lb,fmt,ap);
372
373     while (isspace(*lbp)) lbp++;
374
375     if (lbp && *lbp) 
376         lineCurr = (lineCurr ?
377                     connectLine(lineCurr,newLineNode(lb)) :
378                     (lineHead = newLineNode(lb)));
379     lineCurr->isInline = _G.inLine;
380     lineCurr->isDebug  = _G.debugLine;
381
382 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
383
384 //    if(pic16_debug_verbose)
385 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
386
387     va_end(ap);
388 }
389 #endif
390
391
392 /*-----------------------------------------------------------------*/
393 /* pic16_emitDebuggerSymbol - associate the current code location  */
394 /*   with a debugger symbol                                        */
395 /*-----------------------------------------------------------------*/
396 void
397 pic16_emitDebuggerSymbol (char * debugSym)
398 {
399   _G.debugLine = 1;
400   pic16_emitcode (";", "%s ==.", debugSym);
401   _G.debugLine = 0;
402 }
403
404
405 /*-----------------------------------------------------------------*/
406 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
407 /*-----------------------------------------------------------------*/
408 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
409 {
410 //    bool r0iu = FALSE , r1iu = FALSE;
411 //    bool r0ou = FALSE , r1ou = FALSE;
412     bool fsr0iu = FALSE, fsr0ou;
413     bool fsr2iu = FALSE, fsr2ou;
414     
415     //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__,  __FUNCTION__, __LINE__, ic->op, result);
416
417     
418     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
419     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
420     
421     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
422     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
423
424     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
425         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
426         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
427     }
428
429     if(!fsr0iu && !fsr0ou) {
430         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
431         (*aopp)->type = AOP_FSR0;
432
433         //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
434         
435       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
436     }
437
438 #if 0
439     /* no usage of FSR2 */
440     if(!fsr2iu && !fsr2ou) {
441         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
442         (*aopp)->type = AOP_FSR2;
443
444       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
445     }
446 #endif
447         
448     /* now we know they both have usage */
449     /* if fsr0 not used in this instruction */
450     if (!fsr0iu) {
451         if (!_G.fsr0Pushed) {
452                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
453                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
454                 _G.fsr0Pushed++;
455         }
456
457         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
458         (*aopp)->type = AOP_FSR0;
459
460 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
461
462       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
463     }
464         
465
466     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
467     assert( 0 );
468
469     return NULL;
470 #if 0
471     /* the logic: if r0 & r1 used in the instruction
472     then we are in trouble otherwise */
473
474     /* first check if r0 & r1 are used by this
475     instruction, in which case we are in trouble */
476     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
477         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
478     {
479         goto endOfWorld;      
480     }
481
482     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
483     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
484
485     /* if no usage of r0 then return it */
486     if (!r0iu && !r0ou) {
487         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
488         (*aopp)->type = AOP_R0; 
489         
490         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
491     }
492
493     /* if no usage of r1 then return it */
494     if (!r1iu && !r1ou) {
495         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
496         (*aopp)->type = AOP_R1;
497
498         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
499     }    
500
501     /* now we know they both have usage */
502     /* if r0 not used in this instruction */
503     if (!r0iu) {
504         /* push it if not already pushed */
505         if (!_G.r0Pushed) {
506           //pic16_emitcode ("push","%s",
507           //          pic16_regWithIdx(R0_IDX)->dname);
508             _G.r0Pushed++ ;
509         }
510         
511         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
512         (*aopp)->type = AOP_R0;
513
514         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
515     }
516
517     /* if r1 not used then */
518
519     if (!r1iu) {
520         /* push it if not already pushed */
521         if (!_G.r1Pushed) {
522           //pic16_emitcode ("push","%s",
523           //          pic16_regWithIdx(R1_IDX)->dname);
524             _G.r1Pushed++ ;
525         }
526         
527         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
528         (*aopp)->type = AOP_R1;
529         return pic16_regWithIdx(R1_IDX);
530     }
531
532 endOfWorld :
533     /* I said end of world but not quite end of world yet */
534     /* if this is a result then we can push it on the stack*/
535     if (result) {
536         (*aopp)->type = AOP_STK;    
537         return NULL;
538     }
539
540     /* other wise this is true end of the world */
541     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
542            "getFreePtr should never reach here");
543     exit(0);
544 #endif
545 }
546
547 /*-----------------------------------------------------------------*/
548 /* newAsmop - creates a new asmOp                                  */
549 /*-----------------------------------------------------------------*/
550 static asmop *newAsmop (short type)
551 {
552     asmop *aop;
553
554     aop = Safe_calloc(1,sizeof(asmop));
555     aop->type = type;
556     return aop;
557 }
558
559 static void genSetDPTR(int n)
560 {
561     if (!n)
562     {
563         pic16_emitcode(";", "Select standard DPTR");
564         pic16_emitcode("mov", "dps, #0x00");
565     }
566     else
567     {
568         pic16_emitcode(";", "Select alternate DPTR");
569         pic16_emitcode("mov", "dps, #0x01");
570     }
571 }
572
573 /*-----------------------------------------------------------------*/
574 /* resolveIfx - converts an iCode ifx into a form more useful for  */
575 /*              generating code                                    */
576 /*-----------------------------------------------------------------*/
577 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
578 {
579   FENTRY2;
580   
581 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
582
583   if(!resIfx) 
584     return;
585
586
587   resIfx->condition = 1;    /* assume that the ifx is true */
588   resIfx->generated = 0;    /* indicate that the ifx has not been used */
589
590   if(!ifx) {
591     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
592
593 #if 1
594     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
595                         __FUNCTION__,__LINE__,resIfx->lbl->key);
596 #endif
597
598   } else {
599     if(IC_TRUE(ifx)) {
600       resIfx->lbl = IC_TRUE(ifx);
601     } else {
602       resIfx->lbl = IC_FALSE(ifx);
603       resIfx->condition = 0;
604     }
605
606 #if 1
607     if(IC_TRUE(ifx)) 
608       DEBUGpic16_emitcode("; +++","ifx true is non-null");
609     else
610       DEBUGpic16_emitcode("; +++","ifx true is null");
611     if(IC_FALSE(ifx)) 
612       DEBUGpic16_emitcode("; +++","ifx false is non-null");
613     else
614       DEBUGpic16_emitcode("; +++","ifx false is null");
615 #endif
616   }
617
618   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
619
620 }
621 #if 0
622 /*-----------------------------------------------------------------*/
623 /* pointerCode - returns the code for a pointer type               */
624 /*-----------------------------------------------------------------*/
625 static int pointerCode (sym_link *etype)
626 {
627
628     return PTR_TYPE(SPEC_OCLS(etype));
629
630 }
631 #endif
632
633 /*-----------------------------------------------------------------*/
634 /* aopForSym - for a true symbol                                   */
635 /*-----------------------------------------------------------------*/
636 static asmop *aopForSym (iCode *ic, operand *op, bool result)
637 {
638     symbol *sym=OP_SYMBOL(op);
639     asmop *aop;
640     memmap *space= SPEC_OCLS(sym->etype);
641
642     FENTRY2;
643     
644     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
645     
646 //    sym = OP_SYMBOL(op);
647
648     /* if already has one */
649     if (sym->aop) {
650             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
651         return sym->aop;
652     }
653
654 #if 0
655     /* if symbol was initially placed onStack then we must re-place it
656      * to direct memory, since pic16 does not have a specific stack */
657     if(sym->onStack) {
658         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
659     }
660 #endif
661
662
663 #if 0
664     if(sym->iaccess) {
665       if(space->paged) {
666         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
667
668         sym->aop = aop = newAsmop (AOP_PAGED);
669         aop->aopu.aop_dir = sym->rname ;
670         aop->size = getSize(sym->type);
671         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
672         pic16_allocDirReg( IC_LEFT(ic) );
673         return aop;
674       }
675       assert( 0 );
676     }
677 #endif
678     
679 #if 1
680     /* assign depending on the storage class */
681     /* if it is on the stack or indirectly addressable */
682     /* space we need to assign either r0 or r1 to it   */    
683     if (sym->onStack)   // || sym->iaccess)
684     {
685       pCodeOp *pcop[4];
686       int i;
687       
688         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
689                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
690         
691         /* acquire a temporary register -- it is saved in function */
692
693         sym->aop = aop = newAsmop(AOP_STA);
694         aop->aopu.stk.stk = sym->stack;
695         aop->size = getSize(sym->type);
696
697
698         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
699         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
700           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
701 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
702           
703           for(i=0;i<aop->size;i++)
704             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
705             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
706         } else
707         if(1 && ic->op == SEND) {
708
709           /* if SEND do the send here */
710           _G.resDirect = 1;
711         } else {
712 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
713           for(i=0;i<aop->size;i++) {
714             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
715             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
716           }
717         }
718
719
720 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
721
722 #if 1
723         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
724
725         // we do not need to load the value if it is to be defined...
726         if (result) return aop;
727
728         if(_G.accInUse) {
729                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
730         }
731         
732         for(i=0;i<aop->size;i++) {
733
734           /* initialise for stack access via frame pointer */
735           // operands on stack are accessible via "{FRAME POINTER} + index" with index
736           // starting at 2 for arguments and growing from 0 downwards for
737           // local variables (index == 0 is not assigned so we add one here)
738           {
739             int soffs = sym->stack;
740             if (soffs <= 0) {
741               assert (soffs < 0);
742               soffs++;
743             } // if
744
745             if(1 && ic->op == SEND) {
746               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
747               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
748                     pic16_popCopyReg( pic16_frame_plusw ),
749                     pic16_popCopyReg(pic16_stack_postdec )));
750             } else {
751               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
752               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
753                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
754             }
755           }
756         }
757         
758         if(_G.accInUse) {
759                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
760         }
761         
762         return (aop);
763 #endif
764
765 #if 0
766         /* now assign the address of the variable to 
767         the pointer register */
768         if (aop->type != AOP_STK) {
769
770             if (sym->onStack) {
771                     if ( _G.accInUse )
772                         pic16_emitcode("push","acc");
773
774                     pic16_emitcode("mov","a,_bp");
775                     pic16_emitcode("add","a,#0x%02x",
776                              ((sym->stack < 0) ?
777                               ((char)(sym->stack - _G.nRegsSaved )) :
778                               ((char)sym->stack)) & 0xff);
779                     pic16_emitcode("mov","%s,a",
780                              aop->aopu.aop_ptr->name);
781
782                     if ( _G.accInUse )
783                         pic16_emitcode("pop","acc");
784             } else
785                 pic16_emitcode("mov","%s,#%s",
786                          aop->aopu.aop_ptr->name,
787                          sym->rname);
788             aop->paged = space->paged;
789         } else
790             aop->aopu.aop_stk = sym->stack;
791         return aop;
792 #endif
793
794     }
795 #endif
796
797 #if 0
798     if (sym->onStack && options.stack10bit)
799     {
800         /* It's on the 10 bit stack, which is located in
801          * far data space.
802          */
803          
804       //DEBUGpic16_emitcode(";","%d",__LINE__);
805
806         if ( _G.accInUse )
807                 pic16_emitcode("push","acc");
808
809         pic16_emitcode("mov","a,_bp");
810         pic16_emitcode("add","a,#0x%02x",
811                  ((sym->stack < 0) ?
812                    ((char)(sym->stack - _G.nRegsSaved )) :
813                    ((char)sym->stack)) & 0xff);
814         
815         genSetDPTR(1);
816         pic16_emitcode ("mov","dpx1,#0x40");
817         pic16_emitcode ("mov","dph1,#0x00");
818         pic16_emitcode ("mov","dpl1, a");
819         genSetDPTR(0);
820         
821         if ( _G.accInUse )
822             pic16_emitcode("pop","acc");
823             
824         sym->aop = aop = newAsmop(AOP_DPTR2);
825         aop->size = getSize(sym->type); 
826         return aop;
827     }
828 #endif
829
830 #if 1
831     /* special case for a function */
832     if (IS_FUNC(sym->type)) {   
833         sym->aop = aop = newAsmop(AOP_PCODE);
834         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
835         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
836         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
837         PCOI(aop->aopu.pcop)->index = 0;
838         aop->size = FPTRSIZE; 
839         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
840         return aop;
841     }
842 #endif
843
844
845
846     //DEBUGpic16_emitcode(";","%d",__LINE__);
847     /* if in bit space */
848     if (IN_BITSPACE(space)) {
849         sym->aop = aop = newAsmop (AOP_CRY);
850         aop->aopu.aop_dir = sym->rname ;
851         aop->size = getSize(sym->type);
852         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
853         return aop;
854     }
855     /* if it is in direct space */
856     if (IN_DIRSPACE(space)) {
857                 if(!strcmp(sym->rname, "_WREG")) {
858                         sym->aop = aop = newAsmop (AOP_ACC);
859                         aop->size = getSize(sym->type);         /* should always be 1 */
860                         assert(aop->size == 1);
861                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
862                         return (aop);
863                 } else {
864                         sym->aop = aop = newAsmop (AOP_DIR);
865                 aop->aopu.aop_dir = sym->rname ;
866             aop->size = getSize(sym->type);
867                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
868                         pic16_allocDirReg( IC_LEFT(ic) );
869                         return (aop);
870                 }
871         }
872
873     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
874         sym->aop = aop = newAsmop (AOP_DIR);
875         aop->aopu.aop_dir = sym->rname ;
876         aop->size = getSize(sym->type);
877         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
878         pic16_allocDirReg( IC_LEFT(ic) );
879         return aop;
880     }
881
882
883     /* only remaining is far space */
884     sym->aop = aop = newAsmop(AOP_PCODE);
885
886 /* change the next if to 1 to revert to good old immediate code */
887         if(IN_CODESPACE(space)) {
888                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
889                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
890                 PCOI(aop->aopu.pcop)->index = 0;
891         } else {
892                 /* try to allocate via direct register */
893                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
894 //              aop->size = getSize( sym->type );
895         }
896
897         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
898                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
899
900 #if 0
901         if(!pic16_allocDirReg (IC_LEFT(ic)))
902                 return NULL;
903 #endif
904
905         if(IN_DIRSPACE( space ))
906                 aop->size = PTRSIZE;
907         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
908                 aop->size = FPTRSIZE;
909         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
910         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
911         else if(sym->onStack) {
912                 aop->size = PTRSIZE;
913         } else {
914           if(SPEC_SCLS(sym->etype) == S_PDATA) {
915             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
916             aop->size = FPTRSIZE;
917           } else
918                 assert( 0 );
919         }
920
921     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
922
923     /* if it is in code space */
924     if (IN_CODESPACE(space))
925         aop->code = 1;
926
927     return aop;     
928 }
929
930 /*-----------------------------------------------------------------*/
931 /* aopForRemat - rematerialzes an object                           */
932 /*-----------------------------------------------------------------*/
933 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
934 {
935   symbol *sym = OP_SYMBOL(op);
936   operand *refop;
937   iCode *ic = NULL, *oldic;
938   asmop *aop = newAsmop(AOP_PCODE);
939   int val = 0;
940   int offset = 0;
941   int viaimmd=0;
942
943     FENTRY2;
944     
945         ic = sym->rematiCode;
946
947         if(IS_OP_POINTER(op)) {
948                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
949         }
950
951 //    if(!result)               /* fixme-vr */
952         for (;;) {
953                 oldic = ic;
954
955 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
956         
957                 if (ic->op == '+') {
958                         val += (int) operandLitValue(IC_RIGHT(ic));
959                 } else if (ic->op == '-') {
960                         val -= (int) operandLitValue(IC_RIGHT(ic));
961                 } else
962                         break;
963                 
964                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
965         }
966
967         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
968         refop = IC_LEFT(ic);
969
970         if(!op->isaddr)viaimmd++; else viaimmd=0;
971                 
972 /* set the following if to 1 to revert to good old immediate code */
973         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
974                 || viaimmd) {
975
976                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
977
978                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
979
980 #if 0
981                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
982 #else
983                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
984 #endif
985
986                 PCOI(aop->aopu.pcop)->index = val;
987                 
988                 aop->size = getSize( sym->type );
989         } else {
990                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
991
992                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
993                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
994
995                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
996         }
997
998
999         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1000                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1001 #if 0
1002                 val, IS_PTR_CONST(operandType(op)));
1003 #else
1004                 val, IS_CODEPTR(operandType(op)));
1005 #endif
1006
1007 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1008
1009         pic16_allocDirReg (IC_LEFT(ic));
1010
1011         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1012                 aop->code = 1;
1013
1014   return aop;        
1015 }
1016
1017 #if 0
1018 static int aopIdx (asmop *aop, int offset)
1019 {
1020   if(!aop)
1021     return -1;
1022
1023   if(aop->type !=  AOP_REG)
1024     return -2;
1025         
1026   return aop->aopu.aop_reg[offset]->rIdx;
1027
1028 }
1029 #endif
1030
1031 /*-----------------------------------------------------------------*/
1032 /* regsInCommon - two operands have some registers in common       */
1033 /*-----------------------------------------------------------------*/
1034 static bool regsInCommon (operand *op1, operand *op2)
1035 {
1036     symbol *sym1, *sym2;
1037     int i;
1038
1039     /* if they have registers in common */
1040     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1041         return FALSE ;
1042
1043     sym1 = OP_SYMBOL(op1);
1044     sym2 = OP_SYMBOL(op2);
1045
1046     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1047         return FALSE ;
1048
1049     for (i = 0 ; i < sym1->nRegs ; i++) {
1050         int j;
1051         if (!sym1->regs[i])
1052             continue ;
1053
1054         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1055             if (!sym2->regs[j])
1056                 continue ;
1057
1058             if (sym2->regs[j] == sym1->regs[i])
1059                 return TRUE ;
1060         }
1061     }
1062
1063     return FALSE ;
1064 }
1065
1066 /*-----------------------------------------------------------------*/
1067 /* operandsEqu - equivalent                                        */
1068 /*-----------------------------------------------------------------*/
1069 static bool operandsEqu ( operand *op1, operand *op2)
1070 {
1071     symbol *sym1, *sym2;
1072
1073     /* if they not symbols */
1074     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1075         return FALSE;
1076
1077     sym1 = OP_SYMBOL(op1);
1078     sym2 = OP_SYMBOL(op2);
1079
1080     /* if both are itemps & one is spilt
1081        and the other is not then false */
1082     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1083         sym1->isspilt != sym2->isspilt )
1084         return FALSE ;
1085
1086     /* if they are the same */
1087     if (sym1 == sym2)
1088         return TRUE ;
1089
1090     if (sym1->rname[0] && sym2->rname[0]
1091         && strcmp (sym1->rname, sym2->rname) == 0)
1092         return TRUE;
1093
1094
1095     /* if left is a tmp & right is not */
1096     if (IS_ITEMP(op1)  && 
1097         !IS_ITEMP(op2) &&
1098         sym1->isspilt  &&
1099         (sym1->usl.spillLoc == sym2))
1100         return TRUE;
1101
1102     if (IS_ITEMP(op2)  && 
1103         !IS_ITEMP(op1) &&
1104         sym2->isspilt  &&
1105         sym1->level > 0 &&
1106         (sym2->usl.spillLoc == sym1))
1107         return TRUE ;
1108
1109     return FALSE ;
1110 }
1111
1112 /*-----------------------------------------------------------------*/
1113 /* pic16_sameRegs - two asmops have the same registers                   */
1114 /*-----------------------------------------------------------------*/
1115 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1116 {
1117     int i;
1118
1119     if (aop1 == aop2)
1120         return TRUE ;
1121
1122     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1123                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1124
1125     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1126
1127     if (aop1->type != AOP_REG ||
1128         aop2->type != AOP_REG )
1129         return FALSE ;
1130
1131     /* This is a bit too restrictive if one is a subset of the other...
1132     if (aop1->size != aop2->size )
1133         return FALSE ;
1134     */
1135
1136     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1137 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1138
1139 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1140         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1141             return FALSE ;
1142     }
1143
1144     return TRUE ;
1145 }
1146
1147 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1148 {
1149     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1150                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1151
1152     if(aop1 == aop2)return TRUE;
1153     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1154       
1155       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1156     
1157   return TRUE;
1158 }
1159
1160
1161 /*-----------------------------------------------------------------*/
1162 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1163 /*-----------------------------------------------------------------*/
1164 void pic16_aopOp (operand *op, iCode *ic, bool result)
1165 {
1166     asmop *aop;
1167     symbol *sym;
1168     int i;
1169
1170     if (!op)
1171         return ;
1172
1173     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1174
1175     /* if this a literal */
1176     if (IS_OP_LITERAL(op)) {
1177         op->aop = aop = newAsmop(AOP_LIT);
1178         aop->aopu.aop_lit = op->operand.valOperand;
1179         aop->size = getSize(operandType(op));
1180         return;
1181     }
1182
1183     {
1184       sym_link *type = operandType(op);
1185 #if 0
1186       if(IS_PTR_CONST(type))
1187 #else
1188       if(IS_CODEPTR(type))
1189 #endif
1190         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1191     }
1192
1193     /* if already has a asmop then continue */
1194     if (op->aop)
1195         return ;
1196
1197     /* if the underlying symbol has a aop */
1198     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1199       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1200         op->aop = OP_SYMBOL(op)->aop;
1201         return;
1202     }
1203
1204     /* if this is a true symbol */
1205     if (IS_TRUE_SYMOP(op)) {    
1206         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1207       op->aop = aopForSym(ic, op, result);
1208       return ;
1209     }
1210
1211     /* this is a temporary : this has
1212     only four choices :
1213     a) register
1214     b) spillocation
1215     c) rematerialize 
1216     d) conditional   
1217     e) can be a return use only */
1218
1219     sym = OP_SYMBOL(op);
1220
1221     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1222     /* if the type is a conditional */
1223     if (sym->regType == REG_CND) {
1224         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1225         aop->size = 0;
1226         return;
1227     }
1228
1229     /* if it is spilt then two situations
1230     a) is rematerialize 
1231     b) has a spill location */
1232     if (sym->isspilt || sym->nRegs == 0) {
1233
1234 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1235       DEBUGpic16_emitcode(";","%d",__LINE__);
1236         /* rematerialize it NOW */
1237         if (sym->remat) {
1238
1239             sym->aop = op->aop = aop = aopForRemat (op, result);
1240 //            aop->size = getSize(sym->type);
1241 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1242             return;
1243         }
1244
1245 #if 1
1246         if (sym->accuse) {
1247             int i;
1248             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1249             aop->size = getSize(sym->type);
1250             for ( i = 0 ; i < 1 ; i++ ) {
1251                 aop->aopu.aop_str[i] = accUse[i];
1252 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1253             }
1254             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1255             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1256             return;  
1257         }
1258 #endif
1259
1260 #if 1
1261         if (sym->ruonly) {
1262           /*
1263           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1264           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1265           //pic16_allocDirReg (IC_LEFT(ic));
1266           aop->size = getSize(sym->type);
1267           */
1268
1269           unsigned i;
1270
1271           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1272           aop->size = getSize(sym->type);
1273           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1274             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1275
1276           DEBUGpic16_emitcode(";","%d",__LINE__);
1277           return;
1278         }
1279 #endif
1280         /* else spill location  */
1281         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1282             /* force a new aop if sizes differ */
1283             sym->usl.spillLoc->aop = NULL;
1284         }
1285
1286 #if 0
1287         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1288                             __FUNCTION__,__LINE__,
1289                             sym->usl.spillLoc->rname,
1290                             sym->rname, sym->usl.spillLoc->offset);
1291 #endif
1292
1293         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1294         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1295           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1296           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1297                                                   getSize(sym->type), 
1298                                                   sym->usl.spillLoc->offset, op);
1299         } else if (getSize(sym->type) <= 1) {
1300           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1301           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1302           assert (getSize(sym->type) <= 1);
1303           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1304           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1305         } else {
1306           /* We need some kind of dummy area for getSize(sym->type) byte,
1307            * use WREG for all storage locations.
1308            * XXX: This only works if we are implementing a `dummy read',
1309            *      the stored value will not be retrievable...
1310            *      See #1503234 for a case requiring this. */
1311           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1312           aop->size = getSize(sym->type);
1313           for ( i = 0 ; i < aop->size ;i++)
1314             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1315         }
1316         aop->size = getSize(sym->type);
1317
1318         return;
1319     }
1320
1321     {
1322       sym_link *type = operandType(op);
1323 #if 0
1324       if(IS_PTR_CONST(type)) 
1325 #else
1326       if(IS_CODEPTR(type)) 
1327 #endif
1328         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1329     }
1330
1331     /* must be in a register */
1332     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1333     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1334     aop->size = sym->nRegs;
1335     for ( i = 0 ; i < sym->nRegs ;i++)
1336         aop->aopu.aop_reg[i] = sym->regs[i];
1337 }
1338
1339 /*-----------------------------------------------------------------*/
1340 /* pic16_freeAsmop - free up the asmop given to an operand               */
1341 /*----------------------------------------------------------------*/
1342 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1343 {   
1344     asmop *aop ;
1345
1346     if (!op)
1347         aop = aaop;
1348     else 
1349         aop = op->aop;
1350
1351     if (!aop)
1352         return ;
1353
1354     if (aop->freed)
1355         goto dealloc; 
1356
1357     aop->freed = 1;
1358
1359     /* depending on the asmop type only three cases need work AOP_RO
1360        , AOP_R1 && AOP_STK */
1361 #if 1
1362     switch (aop->type) {
1363         case AOP_FSR0 :
1364             if (_G.fsr0Pushed ) {
1365                 if (pop) {
1366                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1367                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1368 //                    pic16_emitcode ("pop","ar0");
1369                     _G.fsr0Pushed--;
1370                 }
1371             }
1372             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1373             break;
1374
1375         case AOP_FSR2 :
1376             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1377             break;
1378
1379         case AOP_R0 :
1380             if (_G.r0Pushed ) {
1381                 if (pop) {
1382                     pic16_emitcode ("pop","ar0");     
1383                     _G.r0Pushed--;
1384                 }
1385             }
1386             bitVectUnSetBit(ic->rUsed,R0_IDX);
1387             break;
1388
1389         case AOP_R1 :
1390             if (_G.r1Pushed ) {
1391                 if (pop) {
1392                     pic16_emitcode ("pop","ar1");
1393                     _G.r1Pushed--;
1394                 }
1395             }
1396             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1397             break;
1398
1399         case AOP_STA:
1400           {
1401             int i;
1402
1403               /* we must store the result on stack */
1404               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1405                 // operands on stack are accessible via "FSR2 + index" with index
1406                 // starting at 2 for arguments and growing from 0 downwards for
1407                 // local variables (index == 0 is not assigned so we add one here)
1408                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1409                 if (soffs <= 0) {
1410                   assert (soffs < 0);
1411                   soffs++;
1412                 } // if
1413                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1414                 for(i=0;i<aop->size;i++) {
1415                   /* initialise for stack access via frame pointer */
1416                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1417                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1418                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1419                 }
1420         
1421                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1422               }
1423
1424               if(!_G.resDirect) {
1425                 for(i=0;i<aop->size;i++) {
1426                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1427
1428                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1429                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1430 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1431                   }
1432                 }
1433                 
1434                 {
1435                   regs *sr;
1436                   
1437                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1438                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1439                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1440                       deleteSetItem( &_G.sregsAllocSet, sr );
1441                     }
1442                 }
1443               }
1444               _G.resDirect = 0;
1445           }
1446           break;
1447 #if 0
1448         case AOP_STK :
1449         {
1450             int sz = aop->size;    
1451             int stk = aop->aopu.aop_stk + aop->size;
1452             bitVectUnSetBit(ic->rUsed,R0_IDX);
1453             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1454
1455             getFreePtr(ic,&aop,FALSE);
1456             
1457             if (options.stack10bit)
1458             {
1459                 /* I'm not sure what to do here yet... */
1460                 /* #STUB */
1461                 fprintf(stderr, 
1462                         "*** Warning: probably generating bad code for "
1463                         "10 bit stack mode.\n");
1464             }
1465             
1466             if (stk) {
1467                 pic16_emitcode ("mov","a,_bp");
1468                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1469                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1470             } else {
1471                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1472             }
1473
1474             while (sz--) {
1475                 pic16_emitcode("pop","acc");
1476                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1477                 if (!sz) break;
1478                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1479             }
1480             op->aop = aop;
1481             pic16_freeAsmop(op,NULL,ic,TRUE);
1482             if (_G.r0Pushed) {
1483                 pic16_emitcode("pop","ar0");
1484                 _G.r0Pushed--;
1485             }
1486
1487             if (_G.r1Pushed) {
1488                 pic16_emitcode("pop","ar1");
1489                 _G.r1Pushed--;
1490             }       
1491         }
1492 #endif
1493
1494     }
1495 #endif
1496
1497 dealloc:
1498     /* all other cases just dealloc */
1499     if (op ) {
1500         op->aop = NULL;
1501         if (IS_SYMOP(op)) {
1502             OP_SYMBOL(op)->aop = NULL;    
1503             /* if the symbol has a spill */
1504             if (SPIL_LOC(op))
1505                 SPIL_LOC(op)->aop = NULL;
1506         }
1507     }
1508 }
1509
1510 /*-----------------------------------------------------------------*/
1511 /* pic16_aopGet - for fetching value of the aop                          */
1512 /*-----------------------------------------------------------------*/
1513 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1514 {
1515     char *s = buffer ;
1516     char *rs;
1517
1518     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1519
1520     /* offset is greater than size then zero */
1521     if (offset > (aop->size - 1) &&
1522         aop->type != AOP_LIT)
1523         return zero;
1524
1525     /* depending on type */
1526     switch (aop->type) {
1527
1528     case AOP_FSR0:
1529     case AOP_FSR2:
1530       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1531       rs = Safe_calloc(1, strlen(s)+1);
1532       strcpy(rs, s);
1533       return (rs);
1534       
1535 #if 0
1536       /* if we need to increment it */
1537       while (offset > aop->coff)
1538         {
1539           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1540           aop->coff++;
1541         }
1542
1543       while (offset < aop->coff)
1544         {
1545           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1546           aop->coff--;
1547         }
1548       aop->coff = offset;
1549       if (aop->paged)
1550         {
1551           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1552           return (dname ? "acc" : "a");
1553         }
1554       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1555       rs = Safe_calloc (1, strlen (s) + 1);
1556       strcpy (rs, s);
1557       return rs;
1558 #endif
1559
1560         
1561     case AOP_IMMD:
1562         if (bit16) 
1563             sprintf (s,"%s",aop->aopu.aop_immd);
1564         else
1565             if (offset) 
1566                 sprintf(s,"(%s >> %d)",
1567                         aop->aopu.aop_immd,
1568                         offset*8);
1569             else
1570                 sprintf(s,"%s",
1571                         aop->aopu.aop_immd);
1572         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1573         rs = Safe_calloc(1,strlen(s)+1);
1574         strcpy(rs,s);   
1575         return rs;
1576         
1577     case AOP_DIR:
1578       if (offset) {
1579         sprintf(s,"(%s + %d)",
1580                 aop->aopu.aop_dir,
1581                 offset);
1582         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1583       } else
1584             sprintf(s,"%s",aop->aopu.aop_dir);
1585         rs = Safe_calloc(1,strlen(s)+1);
1586         strcpy(rs,s);   
1587         return rs;
1588         
1589     case AOP_REG:
1590       return aop->aopu.aop_reg[offset]->name;
1591         
1592     case AOP_CRY:
1593       return aop->aopu.aop_dir;
1594         
1595     case AOP_ACC:
1596         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1597 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1598 //        assert( 0 );
1599 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1600         rs = Safe_strdup("WREG");
1601         return (rs);
1602
1603     case AOP_LIT:
1604         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1605         rs = Safe_calloc(1,strlen(s)+1);
1606         strcpy(rs,s);   
1607         return rs;
1608         
1609     case AOP_STR:
1610         aop->coff = offset ;
1611
1612 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1613 //          dname)
1614 //          return "acc";
1615         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1616           aop->type = AOP_ACC;
1617           return Safe_strdup("_WREG");
1618         }
1619         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1620         
1621         return aop->aopu.aop_str[offset];
1622         
1623     case AOP_PCODE:
1624       {
1625         pCodeOp *pcop = aop->aopu.pcop;
1626         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1627         if(pcop->name) {
1628           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1629           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1630           if (offset) {
1631             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1632           } else {
1633             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1634           }
1635         } else
1636           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1637
1638       }
1639       rs = Safe_calloc(1,strlen(s)+1);
1640       strcpy(rs,s);   
1641       return rs;
1642
1643 #if 0
1644     case AOP_PAGED:
1645       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1646       if (offset) {
1647         sprintf(s,"(%s + %d)",
1648                 aop->aopu.aop_dir,
1649                 offset);
1650       } else
1651             sprintf(s,"%s",aop->aopu.aop_dir);
1652       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1653       rs = Safe_calloc(1,strlen(s)+1);
1654       strcpy(rs,s);   
1655       return rs;
1656 #endif
1657
1658     case AOP_STA:
1659         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1660         return (rs);
1661         
1662     case AOP_STK:
1663 //        pCodeOp *pcop = aop->aop
1664         break;
1665
1666     }
1667
1668     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1669     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1670            "aopget got unsupported aop->type");
1671     exit(0);
1672 }
1673
1674
1675
1676 /* lock has the following meaning: When allocating temporary registers
1677  * for stack variables storage, the value of the temporary register is
1678  * saved on stack. Its value is restored at the end. This procedure is
1679  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1680  * a possibility that before a call to pic16_aopOp, a temporary register
1681  * is allocated for a while and it is freed after some time, this will
1682  * mess the stack and values will not be restored properly. So use lock=1
1683  * to allocate temporary registers used internally by the programmer, and
1684  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1685  * to inform the compiler developer about a possible bug. This is an internal
1686  * feature for developing the compiler -- VR */
1687  
1688 int _TempReg_lock = 0;
1689 /*-----------------------------------------------------------------*/
1690 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1691 /*-----------------------------------------------------------------*/
1692 pCodeOp *pic16_popGetTempReg(int lock)
1693 {
1694   pCodeOp *pcop=NULL;
1695   symbol *cfunc;
1696
1697 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1698     if(_TempReg_lock) {
1699 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1700     }
1701     
1702     _TempReg_lock += lock;
1703     
1704     cfunc = currFunc;
1705     currFunc = NULL;
1706
1707 #if 0
1708         {
1709           regs *rr;
1710           int i;
1711
1712                 /* this code might seem better but it does the *same* job with
1713                  * the old code, it all depends on ralloc.c to get a free/unused
1714                  * register */
1715          
1716                 i=0;
1717                 while(i < pic16_nRegs) {
1718                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1719                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1720                         if((!rr || (rr && rr->isFree))
1721                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1722                                 pcop = pic16_newpCodeOpReg( i );
1723                                 PCOR(pcop)->r->wasUsed = 1;
1724                                 PCOR(pcop)->r->isFree = 0;
1725                                 break;
1726                         }
1727                         i++;
1728                 }
1729
1730                 if(pcop) {
1731                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1732                 }
1733         }
1734 #else
1735     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1736     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1737       PCOR(pcop)->r->wasUsed=1;
1738       PCOR(pcop)->r->isFree=0;
1739
1740       /* push value on stack */
1741       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1742     }
1743 #endif
1744
1745     currFunc = cfunc;
1746
1747   return pcop;
1748 }
1749
1750 /*-----------------------------------------------------------------*/
1751 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1752 /*                           is not part of f, but don't save if   */
1753 /*                           inside v                              */
1754 /*-----------------------------------------------------------------*/
1755 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1756 {
1757   pCodeOp *pcop=NULL;
1758   symbol *cfunc;
1759   int i;
1760
1761 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1762
1763     if(_TempReg_lock) {
1764 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1765     }
1766
1767     _TempReg_lock += lock;
1768
1769     cfunc = currFunc;
1770     currFunc = NULL;
1771
1772     i = bitVectFirstBit(f);
1773     while(i < 128) {
1774
1775       /* bypass registers that are used by function */
1776       if(!bitVectBitValue(f, i)) {
1777       
1778         /* bypass registers that are already allocated for stack access */
1779         if(!bitVectBitValue(v, i))  {
1780         
1781 //          debugf("getting register rIdx = %d\n", i);
1782           /* ok, get the operand */
1783           pcop = pic16_newpCodeOpReg( i );
1784     
1785           /* should never by NULL */
1786           assert( pcop != NULL );
1787
1788           
1789           /* sanity check */
1790           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1791             int found=0;
1792             
1793               PCOR(pcop)->r->wasUsed=1;
1794               PCOR(pcop)->r->isFree=0;
1795
1796
1797               {
1798                 regs *sr;
1799               
1800                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1801
1802                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1803                       /* already used in previous steps, break */
1804                       found=1;          
1805                       break;
1806                     }
1807                   }
1808               }
1809
1810               /* caller takes care of the following */
1811 //              bitVectSetBit(v, i);
1812
1813               if(!found) {
1814                 /* push value on stack */
1815                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1816                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1817               }
1818           
1819             break;
1820           }
1821         }
1822       }
1823       i++;
1824     }
1825
1826     currFunc = cfunc;
1827
1828   return pcop;
1829 }
1830
1831
1832 /*-----------------------------------------------------------------*/
1833 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1834 /*-----------------------------------------------------------------*/
1835 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1836 {
1837   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1838
1839   _TempReg_lock -= lock;
1840
1841   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1842     PCOR(pcop)->r->isFree = 1;
1843
1844     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1845   }
1846 }
1847 /*-----------------------------------------------------------------*/
1848 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1849 /*-----------------------------------------------------------------*/
1850 pCodeOp *pic16_popGetLabel(int key)
1851 {
1852
1853   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1854
1855   if(key>max_key)
1856     max_key = key;
1857
1858   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1859 }
1860
1861 /*-----------------------------------------------------------------*/
1862 /* pic16_popCopyReg - copy a pcode operator                              */
1863 /*-----------------------------------------------------------------*/
1864 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1865 {
1866   pCodeOpReg *pcor;
1867
1868   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1869   memcpy (pcor, pc, sizeof (pCodeOpReg));
1870   pcor->r->wasUsed = 1;
1871   
1872   //pcor->pcop.type = pc->pcop.type;
1873   if(pc->pcop.name) {
1874     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1875       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1876   } else
1877     pcor->pcop.name = NULL;
1878
1879   //pcor->r = pc->r;
1880   //pcor->rIdx = pc->rIdx;
1881   //pcor->r->wasUsed=1;
1882   //pcor->instance = pc->instance;
1883
1884 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1885
1886   return PCOP(pcor);
1887 }
1888
1889 /*-----------------------------------------------------------------*/
1890 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1891 /*-----------------------------------------------------------------*/
1892 pCodeOp *pic16_popGetLit(int lit)
1893 {
1894   return pic16_newpCodeOpLit(lit);
1895 }
1896
1897 /* Allow for 12 bit literals (LFSR x, <here!>). */
1898 pCodeOp *pic16_popGetLit12(int lit)
1899 {
1900   return pic16_newpCodeOpLit12(lit);
1901 }
1902
1903 /*-----------------------------------------------------------------*/
1904 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1905 /*-----------------------------------------------------------------*/
1906 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1907 {
1908   return pic16_newpCodeOpLit2(lit, arg2);
1909 }
1910
1911
1912 /*-----------------------------------------------------------------*/
1913 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1914 /*-----------------------------------------------------------------*/
1915 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1916 {
1917   return pic16_newpCodeOpImmd(name, offset,index, 0);
1918 }
1919
1920
1921 /*-----------------------------------------------------------------*/
1922 /* pic16_popGet - asm operator to pcode operator conversion              */
1923 /*-----------------------------------------------------------------*/
1924 pCodeOp *pic16_popGetWithString(char *str)
1925 {
1926   pCodeOp *pcop;
1927
1928
1929   if(!str) {
1930     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1931     exit (1);
1932   }
1933
1934   pcop = pic16_newpCodeOp(str,PO_STR);
1935
1936   return pcop;
1937 }
1938
1939 /*-----------------------------------------------------------------*/
1940 /* pic16_popRegFromString -                                        */
1941 /*-----------------------------------------------------------------*/
1942 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1943 {
1944
1945   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1946   pcop->type = PO_DIR;
1947
1948   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1949   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1950
1951   if(!str)
1952     str = "BAD_STRING";
1953
1954   pcop->name = Safe_calloc(1,strlen(str)+1);
1955   strcpy(pcop->name,str);
1956
1957   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1958
1959   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1960 //  PCOR(pcop)->r->wasUsed = 1;
1961
1962   /* make sure that register doesn't exist,
1963    * and operand isn't NULL
1964    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1965   if((PCOR(pcop)->r == NULL) 
1966     && (op)
1967     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1968 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1969 //              __FUNCTION__, __LINE__, str, size, offset);
1970
1971     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1972     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1973
1974   }
1975   PCOR(pcop)->instance = offset;
1976
1977   return pcop;
1978 }
1979
1980 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1981 {
1982   pCodeOp *pcop;
1983
1984 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1985 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1986         
1987         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1988         PCOR(pcop)->rIdx = rIdx;
1989         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1990         if(!PCOR(pcop)->r)
1991                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1992                 
1993         PCOR(pcop)->r->isFree = 0;
1994         PCOR(pcop)->r->wasUsed = 1;
1995
1996         pcop->type = PCOR(pcop)->r->pc_type;
1997
1998   return pcop;
1999 }
2000
2001 /*---------------------------------------------------------------------------------*/
2002 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2003 /*                 VR 030601                                                       */
2004 /*---------------------------------------------------------------------------------*/
2005 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2006 {
2007   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2008         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2009   return PCOP(pcop2);
2010 }
2011
2012
2013
2014 /*--------------------------------------------------------------------------------.-*/
2015 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2016 /*                  VR 030601 , adapted by Hans Dorn                                */
2017 /*--------------------------------------------------------------------------------.-*/
2018 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2019 {
2020   pCodeOp2 *pcop2;
2021   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2022   return PCOP(pcop2);
2023 }
2024
2025 /*---------------------------------------------------------------------------------*/
2026 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2027 /*                     movff instruction                                           */
2028 /*---------------------------------------------------------------------------------*/
2029 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2030 {
2031   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2032         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2033
2034   return PCOP(pcop2);
2035 }
2036
2037
2038 /*-----------------------------------------------------------------*/
2039 /* pic16_popGet - asm operator to pcode operator conversion              */
2040 /*-----------------------------------------------------------------*/
2041 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2042 {
2043 //  char *s = buffer ;
2044 //  char *rs;
2045   pCodeOp *pcop;
2046
2047     FENTRY2;
2048     
2049       /* offset is greater than size then zero */
2050
2051 //    if (offset > (aop->size - 1) &&
2052 //        aop->type != AOP_LIT)
2053 //      return NULL;  //zero;
2054
2055     /* depending on type */
2056     switch (aop->type) {
2057                 case AOP_R0:
2058                 case AOP_R1:
2059                 case AOP_DPTR:
2060                 case AOP_DPTR2:
2061                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2062                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2063                         assert( 0 );
2064                         return NULL;
2065
2066                 case AOP_FSR0:
2067                 case AOP_FSR2:
2068                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2069                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2070                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2071                         PCOR(pcop)->r->wasUsed = 1;
2072                         PCOR(pcop)->r->isFree = 0;
2073       
2074                         PCOR(pcop)->instance = offset;
2075                         pcop->type = PCOR(pcop)->r->pc_type;
2076                         return (pcop);
2077
2078                 case AOP_IMMD:
2079                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2080                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2081
2082                 case AOP_STA:
2083                         /* pCodeOp is already allocated from aopForSym */
2084                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2085                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2086                         return (pcop);
2087       
2088                 case AOP_ACC:
2089                         {
2090                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2091
2092                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2093
2094                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2095         
2096                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2097                                 PCOR(pcop)->rIdx = rIdx;
2098                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2099                                 PCOR(pcop)->r->wasUsed=1;
2100                                 PCOR(pcop)->r->isFree=0;
2101
2102                                 PCOR(pcop)->instance = offset;
2103                                 pcop->type = PCOR(pcop)->r->pc_type;
2104 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2105                                 return pcop;
2106
2107
2108 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2109 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2110
2111 //      assert( 0 );
2112                         }
2113         
2114     case AOP_DIR:
2115       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2116       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2117         
2118 #if 0
2119     case AOP_PAGED:
2120       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2121       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2122 #endif
2123
2124     case AOP_REG:
2125       {
2126         int rIdx;
2127
2128 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
2129 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
2130         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2131
2132         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2133         
2134         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2135 //      pcop->type = PO_GPR_REGISTER;
2136         PCOR(pcop)->rIdx = rIdx;
2137         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2138         PCOR(pcop)->r->wasUsed=1;
2139         PCOR(pcop)->r->isFree=0;
2140
2141         PCOR(pcop)->instance = offset;
2142         pcop->type = PCOR(pcop)->r->pc_type;
2143         
2144         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2145 //      rs = aop->aopu.aop_reg[offset]->name;
2146 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2147         return pcop;
2148       }
2149
2150     case AOP_CRY:
2151         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2152
2153       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2154       PCOR(pcop)->instance = offset;
2155       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2156       //if(PCOR(pcop)->r == NULL)
2157       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2158       return pcop;
2159         
2160     case AOP_LIT:
2161         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2162       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2163
2164     case AOP_STR:
2165       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2166       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2167
2168       /*
2169       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2170       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2171       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2172       pcop->type = PCOR(pcop)->r->pc_type;
2173       pcop->name = PCOR(pcop)->r->name;
2174
2175       return pcop;
2176       */
2177
2178     case AOP_PCODE:
2179       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2180                           __LINE__, 
2181                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2182       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2183       switch( aop->aopu.pcop->type ) {
2184         case PO_DIR: PCOR(pcop)->instance += offset; break;
2185         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2186         case PO_WREG:
2187             assert (offset==0);
2188             break;
2189         default:
2190           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2191           assert( 0 );  /* should never reach here */;
2192       }
2193       return pcop;
2194     }
2195
2196     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2197            "pic16_popGet got unsupported aop->type");
2198     exit(0);
2199 }
2200 /*-----------------------------------------------------------------*/
2201 /* pic16_aopPut - puts a string for a aop                                */
2202 /*-----------------------------------------------------------------*/
2203 void pic16_aopPut (asmop *aop, char *s, int offset)
2204 {
2205     char *d = buffer ;
2206     symbol *lbl ;
2207
2208     return;
2209
2210     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2211
2212     if (aop->size && offset > ( aop->size - 1)) {
2213         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2214                "pic16_aopPut got offset > aop->size");
2215         exit(0);
2216     }
2217
2218     /* will assign value to value */
2219     /* depending on where it is ofcourse */
2220     switch (aop->type) {
2221     case AOP_DIR:
2222       if (offset) {
2223         sprintf(d,"(%s + %d)",
2224                 aop->aopu.aop_dir,offset);
2225         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2226
2227       } else
2228             sprintf(d,"%s",aop->aopu.aop_dir);
2229         
2230         if (strcmp(d,s)) {
2231           DEBUGpic16_emitcode(";","%d",__LINE__);
2232           if(strcmp(s,"W"))
2233             pic16_emitcode("movf","%s,w",s);
2234           pic16_emitcode("movwf","%s",d);
2235
2236           if(strcmp(s,"W")) {
2237             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2238             if(offset >= aop->size) {
2239               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2240               break;
2241             } else
2242               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2243           }
2244
2245           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2246
2247
2248         }
2249         break;
2250         
2251     case AOP_REG:
2252       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2253         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2254           /*
2255             if (*s == '@'           ||
2256                 strcmp(s,"r0") == 0 ||
2257                 strcmp(s,"r1") == 0 ||
2258                 strcmp(s,"r2") == 0 ||
2259                 strcmp(s,"r3") == 0 ||
2260                 strcmp(s,"r4") == 0 ||
2261                 strcmp(s,"r5") == 0 ||
2262                 strcmp(s,"r6") == 0 || 
2263                 strcmp(s,"r7") == 0 )
2264                 pic16_emitcode("mov","%s,%s  ; %d",
2265                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2266             else
2267           */
2268
2269           if(strcmp(s,"W")==0 )
2270             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2271
2272           pic16_emitcode("movwf","%s",
2273                    aop->aopu.aop_reg[offset]->name);
2274
2275           if(strcmp(s,zero)==0) {
2276             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2277
2278           } else if(strcmp(s,"W")==0) {
2279             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2280             pcop->type = PO_GPR_REGISTER;
2281
2282             PCOR(pcop)->rIdx = -1;
2283             PCOR(pcop)->r = NULL;
2284
2285             DEBUGpic16_emitcode(";","%d",__LINE__);
2286             pcop->name = Safe_strdup(s);
2287             pic16_emitpcode(POC_MOVFW,pcop);
2288             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2289           } else if(strcmp(s,one)==0) {
2290             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2291             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2292           } else {
2293             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2294           }
2295         }
2296         break;
2297         
2298     case AOP_DPTR:
2299     case AOP_DPTR2:
2300     
2301     if (aop->type == AOP_DPTR2)
2302     {
2303         genSetDPTR(1);
2304     }
2305     
2306         if (aop->code) {
2307             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2308                    "pic16_aopPut writting to code space");
2309             exit(0);
2310         }
2311         
2312         while (offset > aop->coff) {
2313             aop->coff++;
2314             pic16_emitcode ("inc","dptr");
2315         }
2316         
2317         while (offset < aop->coff) {
2318             aop->coff-- ;
2319             pic16_emitcode("lcall","__decdptr");
2320         }
2321         
2322         aop->coff = offset;
2323         
2324         /* if not in accumulater */
2325         MOVA(s);        
2326         
2327         pic16_emitcode ("movx","@dptr,a");
2328         
2329     if (aop->type == AOP_DPTR2)
2330     {
2331         genSetDPTR(0);
2332     }
2333         break;
2334         
2335     case AOP_R0:
2336     case AOP_R1:
2337         while (offset > aop->coff) {
2338             aop->coff++;
2339             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2340         }
2341         while (offset < aop->coff) {
2342             aop->coff-- ;
2343             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2344         }
2345         aop->coff = offset;
2346         
2347         if (aop->paged) {
2348             MOVA(s);           
2349             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2350             
2351         } else
2352             if (*s == '@') {
2353                 MOVA(s);
2354                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2355             } else
2356                 if (strcmp(s,"r0") == 0 ||
2357                     strcmp(s,"r1") == 0 ||
2358                     strcmp(s,"r2") == 0 ||
2359                     strcmp(s,"r3") == 0 ||
2360                     strcmp(s,"r4") == 0 ||
2361                     strcmp(s,"r5") == 0 ||
2362                     strcmp(s,"r6") == 0 || 
2363                     strcmp(s,"r7") == 0 ) {
2364                     char buffer[10];
2365                     sprintf(buffer,"a%s",s);
2366                     pic16_emitcode("mov","@%s,%s",
2367                              aop->aopu.aop_ptr->name,buffer);
2368                 } else
2369                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2370         
2371         break;
2372         
2373     case AOP_STK:
2374         if (strcmp(s,"a") == 0)
2375             pic16_emitcode("push","acc");
2376         else
2377             pic16_emitcode("push","%s",s);
2378         
2379         break;
2380         
2381     case AOP_CRY:
2382         /* if bit variable */
2383         if (!aop->aopu.aop_dir) {
2384             pic16_emitcode("clr","a");
2385             pic16_emitcode("rlc","a");
2386         } else {
2387             if (s == zero) 
2388                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2389             else
2390                 if (s == one)
2391                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2392                 else
2393                     if (!strcmp(s,"c"))
2394                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2395                     else {
2396                         lbl = newiTempLabel(NULL);
2397                         
2398                         if (strcmp(s,"a")) {
2399                             MOVA(s);
2400                         }
2401                         pic16_emitcode("clr","c");
2402                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2403                         pic16_emitcode("cpl","c");
2404                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2405                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2406                     }
2407         }
2408         break;
2409         
2410     case AOP_STR:
2411         aop->coff = offset;
2412         if (strcmp(aop->aopu.aop_str[offset],s))
2413             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2414         break;
2415         
2416     case AOP_ACC:
2417         aop->coff = offset;
2418         if (!offset && (strcmp(s,"acc") == 0))
2419             break;
2420         
2421         if (strcmp(aop->aopu.aop_str[offset],s))
2422             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2423         break;
2424
2425     default :
2426         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2427 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2428 //             "pic16_aopPut got unsupported aop->type");
2429 //      exit(0);    
2430     }    
2431
2432 }
2433
2434 /*-----------------------------------------------------------------*/
2435 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2436 /*-----------------------------------------------------------------*/
2437 void pic16_mov2w (asmop *aop, int offset)
2438 {
2439   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2440
2441   if(is_LitAOp(aop))
2442     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2443   else
2444     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2445 }
2446
2447 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2448 {
2449   if(is_LitAOp(src)) {
2450     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2451     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2452   } else {
2453     if(pic16_sameRegsOfs(src, dst, offset))return;
2454     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2455                       pic16_popGet(dst, offset)));
2456   }
2457 }
2458
2459 static void pic16_movLit2f(pCodeOp *pc, int lit)
2460 {
2461   if (0 == (lit & 0x00ff))
2462   {
2463     pic16_emitpcode (POC_CLRF, pc);
2464   } else if (0xff == (lit & 0x00ff))
2465   {
2466     pic16_emitpcode (POC_SETF, pc);
2467   } else {
2468     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2469     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2470   }
2471 }
2472
2473 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2474 {
2475   if(is_LitAOp(src)) {
2476     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2477     pic16_emitpcode(POC_MOVWF, dst);
2478   } else {
2479     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2480   }
2481 }
2482
2483 void pic16_testStackOverflow(void)
2484 {
2485 #define GSTACK_TEST_NAME        "_gstack_test"
2486
2487   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2488   
2489   {
2490     symbol *sym;
2491
2492       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2493       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2494 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2495       checkAddSym(&externs, sym);
2496   }
2497
2498 }
2499
2500 /* push pcop into stack */
2501 void pic16_pushpCodeOp(pCodeOp *pcop)
2502 {
2503 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2504   if (pcop->type == PO_LITERAL) {
2505     pic16_emitpcode(POC_MOVLW, pcop);
2506     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2507   } else {
2508     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2509   }
2510   if(pic16_options.gstack)
2511     pic16_testStackOverflow();
2512     
2513 }
2514
2515 /* pop pcop from stack */
2516 void pic16_poppCodeOp(pCodeOp *pcop)
2517 {
2518   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2519   if(pic16_options.gstack)
2520     pic16_testStackOverflow();
2521 }
2522
2523
2524 /*-----------------------------------------------------------------*/
2525 /* pushw - pushes wreg to stack                                    */
2526 /*-----------------------------------------------------------------*/
2527 void pushw(void)
2528 {
2529   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2530   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2531   if(pic16_options.gstack)
2532     pic16_testStackOverflow();
2533 }
2534
2535                 
2536 /*-----------------------------------------------------------------*/
2537 /* pushaop - pushes aop to stack                                   */
2538 /*-----------------------------------------------------------------*/
2539 void pushaop(asmop *aop, int offset)
2540 {
2541   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2542
2543   if(_G.resDirect)return;
2544   
2545   if(is_LitAOp(aop)) {
2546     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2547     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2548   } else {
2549     pic16_emitpcode(POC_MOVFF,
2550       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2551   }
2552
2553   if(pic16_options.gstack)
2554     pic16_testStackOverflow();
2555 }
2556
2557 /*-----------------------------------------------------------------*/
2558 /* popaop - pops aop from stack                                    */
2559 /*-----------------------------------------------------------------*/
2560 void popaop(asmop *aop, int offset)
2561 {
2562   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2563   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2564   if(pic16_options.gstack)
2565     pic16_testStackOverflow();
2566 }
2567
2568 void popaopidx(asmop *aop, int offset, int index)
2569 {
2570   int ofs=1;
2571
2572     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2573
2574     if(STACK_MODEL_LARGE)ofs++;
2575
2576     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2577     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2578     if(pic16_options.gstack)
2579       pic16_testStackOverflow();
2580 }
2581
2582 #if !(USE_GENERIC_SIGNED_SHIFT)
2583 /*-----------------------------------------------------------------*/
2584 /* reAdjustPreg - points a register back to where it should        */
2585 /*-----------------------------------------------------------------*/
2586 static void reAdjustPreg (asmop *aop)
2587 {
2588     int size ;
2589
2590     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2591     aop->coff = 0;
2592     if ((size = aop->size) <= 1)
2593         return ;
2594     size-- ;
2595     switch (aop->type) {
2596         case AOP_R0 :
2597         case AOP_R1 :
2598             while (size--)
2599                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2600             break;          
2601         case AOP_DPTR :
2602         case AOP_DPTR2:
2603             if (aop->type == AOP_DPTR2)
2604             {
2605                 genSetDPTR(1);
2606             } 
2607             while (size--)
2608             {
2609                 pic16_emitcode("lcall","__decdptr");
2610             }
2611                 
2612             if (aop->type == AOP_DPTR2)
2613             {
2614                 genSetDPTR(0);
2615             }                
2616             break;  
2617
2618     }   
2619
2620 }
2621 #endif
2622
2623 #if 0
2624 /*-----------------------------------------------------------------*/
2625 /* opIsGptr: returns non-zero if the passed operand is             */   
2626 /* a generic pointer type.                                         */
2627 /*-----------------------------------------------------------------*/ 
2628 static int opIsGptr(operand *op)
2629 {
2630     sym_link *type = operandType(op);
2631     
2632     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2633     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2634     {
2635         return 1;
2636     }
2637     return 0;        
2638 }
2639 #endif
2640
2641 /*-----------------------------------------------------------------*/
2642 /* pic16_getDataSize - get the operand data size                         */
2643 /*-----------------------------------------------------------------*/
2644 int pic16_getDataSize(operand *op)
2645 {
2646     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2647
2648
2649     return AOP_SIZE(op);
2650
2651     // tsd- in the pic port, the genptr size is 1, so this code here
2652     // fails. ( in the 8051 port, the size was 4).
2653 #if 0
2654     int size;
2655     size = AOP_SIZE(op);
2656     if (size == GPTRSIZE)
2657     {
2658         sym_link *type = operandType(op);
2659         if (IS_GENPTR(type))
2660         {
2661             /* generic pointer; arithmetic operations
2662              * should ignore the high byte (pointer type).
2663              */
2664             size--;
2665     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2666         }
2667     }
2668     return size;
2669 #endif
2670 }
2671
2672 /*-----------------------------------------------------------------*/
2673 /* pic16_outAcc - output Acc                                             */
2674 /*-----------------------------------------------------------------*/
2675 void pic16_outAcc(operand *result)
2676 {
2677   int size,offset;
2678   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2679   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2680
2681
2682   size = pic16_getDataSize(result);
2683   if(size){
2684     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2685     size--;
2686     offset = 1;
2687     /* unsigned or positive */
2688     while(size--)
2689       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2690   }
2691
2692 }
2693
2694 /*-----------------------------------------------------------------*/
2695 /* pic16_outBitC - output a bit C                                  */
2696 /*                 Move to result the value of Carry flag -- VR    */
2697 /*-----------------------------------------------------------------*/
2698 void pic16_outBitC(operand *result)
2699 {
2700   int i;
2701
2702     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2703
2704     /* if the result is bit */
2705     if (AOP_TYPE(result) == AOP_CRY) {
2706         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2707         pic16_aopPut(AOP(result),"c",0);
2708     } else {
2709
2710         i = AOP_SIZE(result);
2711         while(i--) {
2712                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2713         }
2714         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2715     }
2716 }
2717
2718 /*-----------------------------------------------------------------*/
2719 /* pic16_outBitOp - output a bit from Op                           */
2720 /*                 Move to result the value of set/clr op -- VR    */
2721 /*-----------------------------------------------------------------*/
2722 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2723 {
2724   int i;
2725
2726     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2727
2728     /* if the result is bit */
2729     if (AOP_TYPE(result) == AOP_CRY) {
2730         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2731         pic16_aopPut(AOP(result),"c",0);
2732     } else {
2733
2734         i = AOP_SIZE(result);
2735         while(i--) {
2736                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2737         }
2738         pic16_emitpcode(POC_RRCF, pcop);          
2739         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2740     }
2741 }
2742
2743 /*-----------------------------------------------------------------*/
2744 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2745 /*-----------------------------------------------------------------*/
2746 void pic16_toBoolean(operand *oper)
2747 {
2748     int size = AOP_SIZE(oper) - 1;
2749     int offset = 1;
2750
2751     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2752
2753     if ( AOP_TYPE(oper) != AOP_ACC) {
2754       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2755     }
2756     while (size--) {
2757       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2758     }
2759 }
2760
2761 /*-----------------------------------------------------------------*/
2762 /* genUminusFloat - unary minus for floating points                */
2763 /*-----------------------------------------------------------------*/
2764 static void genUminusFloat(operand *op,operand *result)
2765 {
2766   int size ,offset =0 ;
2767   
2768     FENTRY;
2769     /* for this we just need to flip the 
2770     first it then copy the rest in place */
2771     size = AOP_SIZE(op);
2772     assert( size == AOP_SIZE(result) );
2773
2774     while(size--) {
2775       pic16_mov2f(AOP(result), AOP(op), offset);
2776       offset++;
2777     }
2778     
2779     /* toggle the MSB's highest bit */
2780     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2781 }
2782
2783 /*-----------------------------------------------------------------*/
2784 /* genUminus - unary minus code generation                         */
2785 /*-----------------------------------------------------------------*/
2786 static void genUminus (iCode *ic)
2787 {
2788   int size, i;
2789   sym_link *optype, *rtype;
2790   symbol *label;
2791   int needLabel=0;
2792
2793     FENTRY;     
2794     
2795     /* assign asmops */
2796     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2797     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2798
2799     /* if both in bit space then special case */
2800     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2801       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2802         
2803         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2804         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2805         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2806         goto release; 
2807     } 
2808
2809     optype = operandType(IC_LEFT(ic));
2810     rtype = operandType(IC_RESULT(ic));
2811
2812
2813     /* if float then do float stuff */
2814     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2815       if(IS_FIXED(optype))
2816         debugf("implement fixed16x16 type\n", 0);
2817         
2818         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2819         goto release;
2820     }
2821
2822     /* otherwise subtract from zero by taking the 2's complement */
2823     size = AOP_SIZE(IC_LEFT(ic));
2824     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2825     label = newiTempLabel ( NULL );
2826     
2827     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2828       for (i=size-1; i > 0; i--) {
2829         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2830       } // for
2831       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2832       for (i=1; i < size; i++) {
2833         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2834         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2835       } // for
2836     } else {
2837       for (i=size-1; i >= 0; i--) {
2838         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2839         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2840       } // for
2841       if (size > 1) {
2842         for (i=0; i < size-2; i++) {
2843           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2844           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2845         } // for
2846         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2847       } // if
2848       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2849     }
2850     if (needLabel)
2851       pic16_emitpLabel (label->key);
2852
2853 release:
2854     /* release the aops */
2855     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2856     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2857 }
2858
2859 #if 0
2860 /*-----------------------------------------------------------------*/
2861 /* saveRegisters - will look for a call and save the registers     */
2862 /*-----------------------------------------------------------------*/
2863 static void saveRegisters(iCode *lic) 
2864 {
2865     int i;
2866     iCode *ic;
2867     bitVect *rsave;
2868     sym_link *dtype;
2869
2870     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2871     /* look for call */
2872     for (ic = lic ; ic ; ic = ic->next) 
2873         if (ic->op == CALL || ic->op == PCALL)
2874             break;
2875
2876     if (!ic) {
2877         fprintf(stderr,"found parameter push with no function call\n");
2878         return ;
2879     }
2880
2881     /* if the registers have been saved already then
2882     do nothing */
2883     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2884         return ;
2885
2886     /* find the registers in use at this time 
2887     and push them away to safety */
2888     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2889                           ic->rUsed);
2890
2891     ic->regsSaved = 1;
2892     if (options.useXstack) {
2893         if (bitVectBitValue(rsave,R0_IDX))
2894             pic16_emitcode("mov","b,r0");
2895         pic16_emitcode("mov","r0,%s",spname);
2896         for (i = 0 ; i < pic16_nRegs ; i++) {
2897             if (bitVectBitValue(rsave,i)) {
2898                 if (i == R0_IDX)
2899                     pic16_emitcode("mov","a,b");
2900                 else
2901                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2902                 pic16_emitcode("movx","@r0,a");
2903                 pic16_emitcode("inc","r0");
2904             }
2905         }
2906         pic16_emitcode("mov","%s,r0",spname);
2907         if (bitVectBitValue(rsave,R0_IDX))
2908             pic16_emitcode("mov","r0,b");           
2909     }// else
2910     //for (i = 0 ; i < pic16_nRegs ; i++) {
2911     //    if (bitVectBitValue(rsave,i))
2912     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2913     //}
2914
2915     dtype = operandType(IC_LEFT(ic));
2916     if (currFunc && dtype && 
2917         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2918         IFFUNC_ISISR(currFunc->type) &&
2919         !ic->bankSaved) 
2920
2921         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2922
2923 }
2924 /*-----------------------------------------------------------------*/
2925 /* unsaveRegisters - pop the pushed registers                      */
2926 /*-----------------------------------------------------------------*/
2927 static void unsaveRegisters (iCode *ic)
2928 {
2929     int i;
2930     bitVect *rsave;
2931
2932     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2933     /* find the registers in use at this time 
2934     and push them away to safety */
2935     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2936                           ic->rUsed);
2937     
2938     if (options.useXstack) {
2939         pic16_emitcode("mov","r0,%s",spname);   
2940         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2941             if (bitVectBitValue(rsave,i)) {
2942                 pic16_emitcode("dec","r0");
2943                 pic16_emitcode("movx","a,@r0");
2944                 if (i == R0_IDX)
2945                     pic16_emitcode("mov","b,a");
2946                 else
2947                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2948             }       
2949
2950         }
2951         pic16_emitcode("mov","%s,r0",spname);
2952         if (bitVectBitValue(rsave,R0_IDX))
2953             pic16_emitcode("mov","r0,b");
2954     } //else
2955     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2956     //    if (bitVectBitValue(rsave,i))
2957     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2958     //}
2959
2960 }  
2961 #endif
2962
2963 #if 0  // patch 14
2964 /*-----------------------------------------------------------------*/
2965 /* pushSide -                                                      */
2966 /*-----------------------------------------------------------------*/
2967 static void pushSide(operand * oper, int size)
2968 {
2969         int offset = 0;
2970     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2971         while (size--) {
2972                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2973                 if (AOP_TYPE(oper) != AOP_REG &&
2974                     AOP_TYPE(oper) != AOP_DIR &&
2975                     strcmp(l,"a") ) {
2976                         pic16_emitcode("mov","a,%s",l);
2977                         pic16_emitcode("push","acc");
2978                 } else
2979                         pic16_emitcode("push","%s",l);
2980         }
2981 }
2982 #endif // patch 14
2983
2984 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2985 {
2986   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2987     pic16_emitpcode(POC_MOVFW, src);
2988     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2989   } else {
2990     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2991         src, pic16_popGet(AOP(op), offset)));
2992   }
2993 }
2994
2995
2996 /*-----------------------------------------------------------------*/
2997 /* assignResultValue - assign results to oper, rescall==1 is       */
2998 /*                     called from genCall() or genPcall()         */
2999 /*-----------------------------------------------------------------*/
3000 static void assignResultValue(operand * oper, int res_size, int rescall)
3001 {
3002   int size = AOP_SIZE(oper);
3003   int offset=0;
3004   
3005     FENTRY2;
3006 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3007     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3008
3009     if(rescall) {
3010       /* assign result from a call/pcall function() */
3011                 
3012       /* function results are stored in a special order,
3013        * see top of file with Function return policy, or manual */
3014
3015       if(size <= 4) {
3016         /* 8-bits, result in WREG */
3017         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3018                         
3019         if(size > 1 && res_size > 1) {
3020           /* 16-bits, result in PRODL:WREG */
3021           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3022         }
3023                         
3024         if(size > 2 && res_size > 2) {
3025           /* 24-bits, result in PRODH:PRODL:WREG */
3026           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3027         }
3028                         
3029         if(size > 3 && res_size > 3) {
3030           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3031           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3032         }
3033
3034         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3035       
3036       } else {
3037         /* >32-bits, result on stack, and FSR0 points to beginning.
3038          * Fix stack when done */
3039         /* FIXME FIXME */
3040 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3041         while (size--) {
3042 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3043 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3044                 
3045           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3046           GpsuedoStkPtr++;
3047         }
3048                         
3049         /* fix stack */
3050         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3051         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3052         if(STACK_MODEL_LARGE) {
3053           emitSKPNC;
3054           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3055         }
3056       }                 
3057     } else {
3058       int areg = 0;             /* matching argument register */
3059       
3060 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3061       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3062
3063
3064       /* its called from genReceive (probably) -- VR */
3065       /* I hope this code will not be called from somewhere else in the future! 
3066        * We manually set the pseudo stack pointer in genReceive. - dw
3067        */
3068       if(!GpsuedoStkPtr && _G.useWreg) {
3069 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3070
3071         /* The last byte in the assignment is in W */
3072         if(areg <= GpsuedoStkPtr) {
3073           size--;
3074           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3075           offset++;
3076 //          debugf("receive from WREG\n", 0);
3077         }
3078         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3079       }
3080 //      GpsuedoStkPtr++;
3081       _G.stack_lat = AOP_SIZE(oper)-1;
3082
3083       while (size) {
3084         size--;
3085         GpsuedoStkPtr++;
3086         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3087 //        debugf("receive from STACK\n", 0);
3088         offset++;
3089       }
3090     }
3091 }
3092
3093
3094 /*-----------------------------------------------------------------*/
3095 /* genIpush - generate code for pushing this gets a little complex */
3096 /*-----------------------------------------------------------------*/
3097 static void genIpush (iCode *ic)
3098 {
3099 //  int size, offset=0;
3100
3101   FENTRY;
3102   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3103
3104   if(ic->parmPush) {
3105     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3106
3107     /* send to stack as normal */
3108     addSet(&_G.sendSet,ic);
3109 //    addSetHead(&_G.sendSet,ic);
3110     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3111   }
3112
3113         
3114 #if 0
3115     int size, offset = 0 ;
3116     char *l;
3117
3118
3119     /* if this is not a parm push : ie. it is spill push 
3120     and spill push is always done on the local stack */
3121     if (!ic->parmPush) {
3122
3123         /* and the item is spilt then do nothing */
3124         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3125             return ;
3126
3127         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3128         size = AOP_SIZE(IC_LEFT(ic));
3129         /* push it on the stack */
3130         while(size--) {
3131             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3132             if (*l == '#') {
3133                 MOVA(l);
3134                 l = "acc";
3135             }
3136             pic16_emitcode("push","%s",l);
3137         }
3138         return ;        
3139     }
3140
3141     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3142 #endif
3143 }
3144
3145 /*-----------------------------------------------------------------*/
3146 /* genIpop - recover the registers: can happen only for spilling   */
3147 /*-----------------------------------------------------------------*/
3148 static void genIpop (iCode *ic)
3149 {
3150   FENTRY;
3151   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3152 #if 0
3153     int size,offset ;
3154
3155
3156     /* if the temp was not pushed then */
3157     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3158         return ;
3159
3160     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3161     size = AOP_SIZE(IC_LEFT(ic));
3162     offset = (size-1);
3163     while (size--) 
3164         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3165                                    FALSE,TRUE));
3166
3167     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3168 #endif
3169 }
3170
3171 #if 0
3172 /*-----------------------------------------------------------------*/
3173 /* unsaverbank - restores the resgister bank from stack            */
3174 /*-----------------------------------------------------------------*/
3175 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3176 {
3177   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3178 #if 0
3179     int i;
3180     asmop *aop ;
3181     regs *r = NULL;
3182
3183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3184     if (popPsw) {
3185         if (options.useXstack) {
3186             aop = newAsmop(0);
3187             r = getFreePtr(ic,&aop,FALSE);
3188             
3189             
3190             pic16_emitcode("mov","%s,_spx",r->name);
3191             pic16_emitcode("movx","a,@%s",r->name);
3192             pic16_emitcode("mov","psw,a");
3193             pic16_emitcode("dec","%s",r->name);
3194             
3195         }else
3196             pic16_emitcode ("pop","psw");
3197     }
3198
3199     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3200         if (options.useXstack) {       
3201             pic16_emitcode("movx","a,@%s",r->name);
3202             //pic16_emitcode("mov","(%s+%d),a",
3203             //       regspic16[i].base,8*bank+regspic16[i].offset);
3204             pic16_emitcode("dec","%s",r->name);
3205
3206         } else 
3207           pic16_emitcode("pop",""); //"(%s+%d)",
3208         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3209     }
3210
3211     if (options.useXstack) {
3212
3213         pic16_emitcode("mov","_spx,%s",r->name);
3214         pic16_freeAsmop(NULL,aop,ic,TRUE);
3215
3216     }
3217 #endif 
3218 }
3219
3220 /*-----------------------------------------------------------------*/
3221 /* saverbank - saves an entire register bank on the stack          */
3222 /*-----------------------------------------------------------------*/
3223 static void saverbank (int bank, iCode *ic, bool pushPsw)
3224 {
3225   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3226 #if 0
3227     int i;
3228     asmop *aop ;
3229     regs *r = NULL;
3230
3231     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3232     if (options.useXstack) {
3233
3234         aop = newAsmop(0);
3235         r = getFreePtr(ic,&aop,FALSE);  
3236         pic16_emitcode("mov","%s,_spx",r->name);
3237
3238     }
3239
3240     for (i = 0 ; i < pic16_nRegs ;i++) {
3241         if (options.useXstack) {
3242             pic16_emitcode("inc","%s",r->name);
3243             //pic16_emitcode("mov","a,(%s+%d)",
3244             //         regspic16[i].base,8*bank+regspic16[i].offset);
3245             pic16_emitcode("movx","@%s,a",r->name);           
3246         } else 
3247           pic16_emitcode("push","");// "(%s+%d)",
3248                      //regspic16[i].base,8*bank+regspic16[i].offset);
3249     }
3250     
3251     if (pushPsw) {
3252         if (options.useXstack) {
3253             pic16_emitcode("mov","a,psw");
3254             pic16_emitcode("movx","@%s,a",r->name);     
3255             pic16_emitcode("inc","%s",r->name);
3256             pic16_emitcode("mov","_spx,%s",r->name);       
3257             pic16_freeAsmop (NULL,aop,ic,TRUE);
3258             
3259         } else
3260             pic16_emitcode("push","psw");
3261         
3262         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3263     }
3264     ic->bankSaved = 1;
3265 #endif
3266 }
3267 #endif  /* 0 */
3268
3269
3270 static int wparamCmp(void *p1, void *p2)
3271 {
3272   return (!strcmp((char *)p1, (char *)p2));
3273 }
3274
3275 int inWparamList(char *s)
3276 {
3277   return isinSetWith(wparamList, s, wparamCmp);
3278
3279
3280
3281 /*-----------------------------------------------------------------*/
3282 /* genCall - generates a call statement                            */
3283 /*-----------------------------------------------------------------*/
3284 static void genCall (iCode *ic)
3285 {
3286   sym_link *ftype;   
3287   int stackParms=0;
3288   int use_wreg=0;
3289   int inwparam=0;
3290   char *fname;
3291   
3292     FENTRY;
3293
3294     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3295     /* if caller saves & we have not saved then */
3296 //    if (!ic->regsSaved)
3297 //      saveRegisters(ic);
3298
3299         /* initialise stackParms for IPUSH pushes */
3300 //      stackParms = psuedoStkPtr;
3301 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3302     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3303     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3304
3305 #if 0
3306     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3307 #endif
3308
3309     /* if send set is not empty the assign */
3310     if (_G.sendSet) {
3311       iCode *sic;
3312       int psuedoStkPtr=-1; 
3313       int firstTimeThruLoop = 1;
3314
3315
3316         /* reverse sendSet if function is not reentrant */
3317         if(!IFFUNC_ISREENT(ftype))
3318           _G.sendSet = reverseSet(_G.sendSet);
3319
3320         /* First figure how many parameters are getting passed */
3321         stackParms = 0;
3322         use_wreg = 0;
3323         
3324         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3325           int size;
3326 //          int offset = 0;
3327
3328             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3329             size = AOP_SIZE(IC_LEFT(sic));
3330
3331             stackParms += size;
3332
3333             /* pass the last byte through WREG */
3334             if(inwparam) {
3335
3336               while (size--) {
3337                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3338                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3339                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3340
3341                 if(!firstTimeThruLoop) {
3342                   /* If this is not the first time we've been through the loop
3343                    * then we need to save the parameter in a temporary
3344                    * register. The last byte of the last parameter is
3345                    * passed in W. */
3346
3347                   pushw();
3348 //                  --psuedoStkPtr;             // sanity check
3349                   use_wreg = 1;
3350                 }
3351                 
3352                 firstTimeThruLoop=0;
3353
3354                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3355
3356 //                offset++;
3357               }
3358             } else {
3359               /* all arguments are passed via stack */
3360               use_wreg = 0;
3361
3362               while (size--) {
3363                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3364                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3365                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3366
3367 //                pushaop(AOP(IC_LEFT(sic)), size);
3368                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3369                                 
3370                 if(!_G.resDirect)
3371                   pushw();
3372               }
3373             }
3374
3375             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3376           }
3377
3378           if(inwparam) {
3379             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3380               pushw();  /* save last parameter to stack if functions has varargs */
3381               use_wreg = 0;
3382             } else
3383               use_wreg = 1;
3384           } else use_wreg = 0;
3385
3386           _G.stackRegSet = _G.sendSet;
3387           _G.sendSet = NULL;
3388     }
3389
3390     /* make the call */
3391     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3392
3393     GpsuedoStkPtr=0;
3394     
3395     /* if we need to assign a result value */
3396     if ((IS_ITEMP(IC_RESULT(ic))
3397           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3398               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3399         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3400
3401       _G.accInUse++;
3402       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3403       _G.accInUse--;
3404
3405       /* Must not assign an 8-bit result to a 16-bit variable;
3406        * this would use (used...) the uninitialized PRODL! */
3407       /* FIXME: Need a proper way to obtain size of function result type,
3408        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3409       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3410
3411       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3412                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3413                 
3414       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3415     }
3416
3417     if(!stackParms && ic->parmBytes) {
3418       stackParms = ic->parmBytes;
3419     }
3420       
3421     stackParms -= use_wreg;
3422     
3423     if(stackParms>0) {
3424       if(stackParms == 1) {
3425         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3426       } else {
3427         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3428         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3429       }
3430       if(STACK_MODEL_LARGE) {
3431         emitSKPNC;
3432         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3433       }
3434     }
3435
3436 #if 0
3437     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3438 #endif
3439
3440     /* adjust the stack for parameters if required */
3441 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3442
3443 #if 0
3444       /* if register bank was saved then pop them */
3445       if (ic->bankSaved)
3446         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3447
3448       /* if we hade saved some registers then unsave them */
3449       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3450         unsaveRegisters (ic);
3451 #endif
3452 }
3453
3454
3455
3456 /*-----------------------------------------------------------------*/
3457 /* genPcall - generates a call by pointer statement                */
3458 /*            new version, created from genCall - HJD              */
3459 /*-----------------------------------------------------------------*/
3460 static void genPcall (iCode *ic)
3461 {
3462   sym_link *fntype;
3463   int stackParms=0;
3464   symbol *retlbl = newiTempLabel(NULL);
3465   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3466   
3467     FENTRY;
3468
3469     fntype = operandType( IC_LEFT(ic) )->next;
3470
3471     /* if send set is not empty the assign */
3472     if (_G.sendSet) {
3473       iCode *sic;
3474       int psuedoStkPtr=-1; 
3475
3476       /* reverse sendSet if function is not reentrant */
3477       if(!IFFUNC_ISREENT(fntype))
3478         _G.sendSet = reverseSet(_G.sendSet);
3479
3480       stackParms = 0;
3481       
3482       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3483         int size;
3484
3485           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3486           size = AOP_SIZE(IC_LEFT(sic));
3487           stackParms += size;
3488
3489           /* all parameters are passed via stack, since WREG is clobbered
3490            * by the calling sequence */
3491           while (size--) {
3492             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3493             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3494             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3495
3496             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3497             pushw();
3498           }
3499
3500           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3501       }
3502
3503       _G.stackRegSet = _G.sendSet;
3504       _G.sendSet = NULL;
3505     }
3506
3507     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3508
3509     // push return address
3510     // push $ on return stack, then replace with retlbl
3511
3512     /* Thanks to Thorsten Klose for pointing out that the following
3513      * snippet should be interrupt safe */
3514     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3515     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3516
3517     pic16_emitpcodeNULLop(POC_PUSH);
3518
3519     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3520     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3521     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3522     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3523     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3524     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3525
3526
3527     /* restore interrupt control register */
3528     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3530
3531     /* make the call by writing the pointer into pc */
3532     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3533     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3534
3535     // note: MOVFF to PCL not allowed
3536     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3537     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3538
3539
3540     /* return address is here: (X) */
3541     pic16_emitpLabelFORCE(retlbl->key);
3542
3543     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3544
3545     GpsuedoStkPtr=0;
3546     /* if we need assign a result value */
3547     if ((IS_ITEMP(IC_RESULT(ic))
3548           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3549               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3550         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3551
3552       _G.accInUse++;
3553       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3554       _G.accInUse--;
3555
3556       /* FIXME: Need proper way to obtain the function result's type.
3557        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3558       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3559
3560       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3561               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3562                 
3563       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3564     }
3565
3566 //    stackParms -= use_wreg;
3567     
3568     if(stackParms>0) {
3569       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3570       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3571       if(STACK_MODEL_LARGE) {
3572         emitSKPNC;
3573         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3574       }
3575     }
3576 }
3577
3578 /*-----------------------------------------------------------------*/
3579 /* resultRemat - result  is rematerializable                       */
3580 /*-----------------------------------------------------------------*/
3581 static int resultRemat (iCode *ic)
3582 {
3583   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3584   if (SKIP_IC(ic) || ic->op == IFX)
3585     return 0;
3586
3587   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3588     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3589     if (sym->remat && !POINTER_SET(ic)) 
3590       return 1;
3591   }
3592
3593   return 0;
3594 }
3595
3596 #if defined(__BORLANDC__) || defined(_MSC_VER)
3597 #define STRCASECMP stricmp
3598 #else
3599 #define STRCASECMP strcasecmp
3600 #endif
3601
3602 #if 0
3603 /*-----------------------------------------------------------------*/
3604 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3605 /*-----------------------------------------------------------------*/
3606 static bool inExcludeList(char *s)
3607 {
3608   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3609     int i =0;
3610     
3611     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3612     if (options.excludeRegs[i] &&
3613     STRCASECMP(options.excludeRegs[i],"none") == 0)
3614         return FALSE ;
3615
3616     for ( i = 0 ; options.excludeRegs[i]; i++) {
3617         if (options.excludeRegs[i] &&
3618         STRCASECMP(s,options.excludeRegs[i]) == 0)
3619             return TRUE;
3620     }
3621     return FALSE ;
3622 }
3623 #endif
3624
3625 /*-----------------------------------------------------------------*/
3626 /* genFunction - generated code for function entry                 */
3627 /*-----------------------------------------------------------------*/
3628 static void genFunction (iCode *ic)
3629 {
3630   symbol *sym;
3631   sym_link *ftype;
3632   
3633     FENTRY;
3634     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3635
3636     pic16_labelOffset += (max_key+4);
3637     max_key=0;
3638     GpsuedoStkPtr=0;
3639     _G.nRegsSaved = 0;
3640         
3641     ftype = operandType(IC_LEFT(ic));
3642     sym = OP_SYMBOL(IC_LEFT(ic));
3643
3644     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3645       /* create an absolute section at the interrupt vector:
3646        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3647       symbol *asym;
3648       char asymname[128];
3649       pBlock *apb;
3650
3651 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3652
3653         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3654           sprintf(asymname, "ivec_%s", sym->name);
3655         else
3656           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3657   
3658         /* when an interrupt is declared as naked, do not emit the special
3659          * wrapper segment at vector address. The user should take care for
3660          * this instead. -- VR */
3661
3662         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3663           asym = newSymbol(asymname, 0);
3664           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3665           pic16_addpBlock( apb );
3666
3667           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3668           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3669           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3670           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3671           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3672                 
3673           /* mark the end of this tiny function */
3674           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3675         } else {
3676           sprintf(asymname, "%s", sym->rname);
3677         }
3678
3679         {
3680           absSym *abSym;
3681
3682             abSym = Safe_calloc(1, sizeof(absSym));
3683             strcpy(abSym->name, asymname);
3684
3685             switch( FUNC_INTNO(sym->type) ) {
3686               case 0: abSym->address = 0x000000; break;
3687               case 1: abSym->address = 0x000008; break;
3688               case 2: abSym->address = 0x000018; break;
3689               
3690               default:
3691 //                fprintf(stderr, "no interrupt number is given\n");
3692                 abSym->address = -1; break;
3693             }
3694
3695             /* relocate interrupt vectors if needed */
3696             if(abSym->address != -1)
3697               abSym->address += pic16_options.ivt_loc;
3698
3699             addSet(&absSymSet, abSym);
3700         }
3701     }
3702
3703     /* create the function header */
3704     pic16_emitcode(";","-----------------------------------------");
3705     pic16_emitcode(";"," function %s",sym->name);
3706     pic16_emitcode(";","-----------------------------------------");
3707
3708     /* prevent this symbol from being emitted as 'extern' */
3709     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3710
3711     pic16_emitcode("","%s:",sym->rname);
3712     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3713
3714     {
3715       absSym *ab;
3716
3717         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3718           if(!strcmp(ab->name, sym->rname)) {
3719             pic16_pBlockConvert2Absolute(pb);
3720             break;
3721           }
3722         }
3723     }
3724
3725     if(IFFUNC_ISNAKED(ftype)) {
3726       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3727       return;
3728     }
3729         
3730     /* if critical function then turn interrupts off */
3731     if (IFFUNC_ISCRITICAL(ftype)) {
3732       //pic16_emitcode("clr","ea");
3733     }
3734
3735     currFunc = sym;             /* update the currFunc symbol */
3736     _G.fregsUsed = sym->regsUsed;
3737     _G.sregsAlloc = newBitVect(128);
3738     
3739
3740     /* if this is an interrupt service routine then
3741      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3742     if (IFFUNC_ISISR(sym->type)) {
3743         _G.usefastretfie = 1;   /* use shadow registers by default */
3744         
3745         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3746         if(!FUNC_ISSHADOWREGS(sym->type)) {
3747           /* do not save WREG,STATUS,BSR for high priority interrupts
3748            * because they are stored in the hardware shadow registers already */
3749           _G.usefastretfie = 0;
3750           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3751           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3752           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3753         }
3754
3755         /* these should really be optimized somehow, because not all
3756          * interrupt handlers modify them */
3757         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3758         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3759         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3760         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3761         
3762 //        pic16_pBlockConvert2ISR(pb);
3763     }
3764
3765     /* emit code to setup stack frame if user enabled,
3766      * and function is not main() */
3767     
3768 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3769     if(strcmp(sym->name, "main")) {
3770       if(0 
3771         || !options.ommitFramePtr 
3772 //        || sym->regsUsed
3773         || IFFUNC_ARGS(sym->type)
3774         || FUNC_HASSTACKPARM(sym->etype)
3775         ) {
3776         /* setup the stack frame */
3777         if(STACK_MODEL_LARGE)
3778           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3779         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3780
3781         if(STACK_MODEL_LARGE)
3782           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3783         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3784       }
3785     }
3786
3787     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3788           && sym->stack) {
3789
3790       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3791
3792       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3793       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3794       emitSKPC;
3795       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3796     }
3797           
3798     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3799       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3800         _G.useWreg = 0;
3801       else
3802         _G.useWreg = 1;
3803     } else
3804       _G.useWreg = 0;
3805
3806     /* if callee-save to be used for this function
3807      * then save the registers being used in this function */
3808 //    if (IFFUNC_CALLEESAVES(sym->type))
3809     if(strcmp(sym->name, "main")) {
3810       int i;
3811
3812         /* if any registers used */
3813         if (sym->regsUsed) {
3814                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3815
3816           if(!xinst) {
3817             /* save the registers used */
3818             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3819             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3820               if (bitVectBitValue(sym->regsUsed,i)) {
3821 #if 0
3822                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3823 #endif
3824                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3825                 _G.nRegsSaved++;
3826
3827                 if(!pic16_regWithIdx(i)->wasUsed) {
3828                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3829                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3830                   pic16_regWithIdx(i)->wasUsed = 1;
3831                 }
3832               }
3833             }
3834           } else {
3835             
3836             /* xinst */
3837             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3838             for(i=0;i<sym->regsUsed->size;i++) {
3839               if(bitVectBitValue(sym->regsUsed, i)) {
3840                 _G.nRegsSaved++;
3841               }
3842             }
3843                         
3844 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3845           }
3846
3847           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3848
3849         }
3850     }
3851         
3852     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3853 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3854 }
3855
3856 /*-----------------------------------------------------------------*/
3857 /* genEndFunction - generates epilogue for functions               */
3858 /*-----------------------------------------------------------------*/
3859 static void genEndFunction (iCode *ic)
3860 {
3861   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3862
3863     FENTRY;
3864
3865     if(IFFUNC_ISNAKED(sym->type)) {
3866       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3867       return;
3868     }
3869
3870     _G.stack_lat = 0;
3871
3872     /* add code for ISCRITICAL */
3873     if(IFFUNC_ISCRITICAL(sym->type)) {
3874       /* if critical function, turn on interrupts */
3875       
3876       /* TODO: add code here -- VR */
3877     }
3878     
3879 //    sym->regsUsed = _G.fregsUsed;
3880     
3881     /* now we need to restore the registers */
3882     /* if any registers used */
3883
3884     /* first restore registers that might be used for stack access */
3885     if(_G.sregsAllocSet) {
3886     regs *sr;
3887     
3888       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3889       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3890         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3891       }
3892     }
3893
3894     if (strcmp(sym->name, "main") && sym->regsUsed) {
3895       int i;
3896
3897         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3898         /* restore registers used */
3899         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3900         for ( i = sym->regsUsed->size; i >= 0; i--) {
3901           if (bitVectBitValue(sym->regsUsed,i)) {
3902             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3903             _G.nRegsSaved--;
3904           }
3905         }
3906         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3907     }
3908
3909       
3910
3911     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3912           && sym->stack) {
3913       if (sym->stack == 1) {
3914         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3915         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3916       } else {
3917         // we have to add more than one...
3918         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3919         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3920         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3921         emitSKPNC;
3922         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3923         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3924         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3925       }
3926     }
3927
3928     if(strcmp(sym->name, "main")) {
3929       if(0
3930         || !options.ommitFramePtr
3931 //        || sym->regsUsed
3932         || IFFUNC_ARGS(sym->type)
3933         || FUNC_HASSTACKPARM(sym->etype)
3934         ) {
3935         /* restore stack frame */
3936         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3937         if(STACK_MODEL_LARGE)
3938           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3939       }
3940     }
3941
3942     _G.useWreg = 0;
3943
3944     if (IFFUNC_ISISR(sym->type)) {
3945       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3946       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3947       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3948       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3949
3950       if(!FUNC_ISSHADOWREGS(sym->type)) {
3951         /* do not restore interrupt vector for WREG,STATUS,BSR
3952          * for high priority interrupt, see genFunction */
3953         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3954         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3955         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3956       }
3957 //      _G.interruptvector = 0;         /* sanity check */
3958
3959
3960       /* if debug then send end of function */
3961 /*      if (options.debug && currFunc)  */
3962       if (currFunc) {
3963         debugFile->writeEndFunction (currFunc, ic, 1);
3964       }
3965         
3966       if(_G.usefastretfie)
3967         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3968       else
3969         pic16_emitpcodeNULLop(POC_RETFIE);
3970
3971       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3972       
3973       _G.usefastretfie = 0;
3974       return;
3975     }
3976
3977     if (IFFUNC_ISCRITICAL(sym->type)) {
3978       pic16_emitcode("setb","ea");
3979     }
3980
3981     /* if debug then send end of function */
3982     if (currFunc) {
3983       debugFile->writeEndFunction (currFunc, ic, 1);
3984     }
3985
3986     /* insert code to restore stack frame, if user enabled it
3987      * and function is not main() */
3988          
3989
3990     pic16_emitpcodeNULLop(POC_RETURN);
3991
3992     /* Mark the end of a function */
3993     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3994 }
3995
3996
3997 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3998 {
3999   unsigned long lit=1;
4000   operand *op;
4001   
4002     op = IC_LEFT(ic);
4003   
4004     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4005     if(AOP_TYPE(op) == AOP_LIT) {
4006       if(!IS_FLOAT(operandType( op ))) {
4007         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4008       } else {
4009         union {
4010           unsigned long lit_int;
4011           float lit_float;
4012         } info;
4013         
4014         /* take care if literal is a float */
4015         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4016         lit = info.lit_int;
4017       }
4018     }
4019
4020     if (AOP_TYPE(op) == AOP_LIT) {
4021       /* FIXME: broken for
4022        *   char __at(0x456) foo;
4023        *   return &foo;
4024        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4025       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4026     } else if (AOP_TYPE(op) == AOP_PCODE
4027                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4028       /* char *s= "aaa"; return s; */
4029       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4030        *      that the generic pointer is interpreted correctly
4031        *      as referring to __code space, but this is fragile! */
4032       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4033       /* XXX: should check that dest != WREG */
4034       pic16_emitpcode(POC_MOVWF, dest);
4035     } else {
4036       if(dest->type == PO_WREG && (offset == 0)) {
4037         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4038         return;
4039       }
4040       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4041     }
4042 }
4043
4044 /*-----------------------------------------------------------------*/
4045 /* genRet - generate code for return statement                     */
4046 /*-----------------------------------------------------------------*/
4047 static void genRet (iCode *ic)
4048 {
4049   int size;
4050   operand *left;
4051
4052     FENTRY;
4053         /* if we have no return value then
4054          * just generate the "ret" */
4055         
4056         if (!IC_LEFT(ic)) 
4057                 goto jumpret;       
4058     
4059         /* we have something to return then
4060          * move the return value into place */
4061         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4062         size = AOP_SIZE(IC_LEFT(ic));
4063
4064         if(size <= 4) {
4065           if(size>3)
4066             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4067           
4068           if(size>2)
4069             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4070
4071           if(size>1)
4072             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4073           
4074           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4075
4076         } else {
4077                 /* >32-bits, setup stack and FSR0 */
4078                 while (size--) {
4079 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4080 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4081
4082                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4083
4084 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4085                         GpsuedoStkPtr++;
4086                 }
4087                         
4088                 /* setup FSR0 */
4089                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4090                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4091
4092                 if(STACK_MODEL_LARGE) {
4093                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4094                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4095                 } else {
4096                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4097                 }
4098         }
4099                                 
4100 #if 0
4101         /* old code, left here for reference -- VR */    
4102         while (size--) {
4103           char *l ;
4104
4105                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4106                         /* #NOCHANGE */
4107                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4108                         pic16_emitpcomment("push %s",l);
4109                         pushed++;
4110                 } else {
4111                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4112                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4113                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4114                         
4115                         if (strcmp(fReturn[offset],l)) {
4116                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4117                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4118                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4119                                 } else {
4120                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4121                                 }
4122                                 
4123                                 if(size) {
4124                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4125                                 }
4126                                 offset++;
4127                         }
4128                 }
4129         }    
4130
4131         if (pushed) {
4132                 while(pushed) {
4133                         pushed--;
4134                         if (strcmp(fReturn[pushed],"a"))
4135                                 pic16_emitcode("pop",fReturn[pushed]);
4136                         else
4137                                 pic16_emitcode("pop","acc");
4138                 }
4139         }
4140 #endif
4141
4142
4143         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4144     
4145 jumpret:
4146         /* generate a jump to the return label
4147          * if the next is not the return statement */
4148         if (!(ic->next && ic->next->op == LABEL
4149                 && IC_LABEL(ic->next) == returnLabel)) {
4150         
4151                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4152                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4153         }
4154 }
4155
4156 /*-----------------------------------------------------------------*/
4157 /* genLabel - generates a label                                    */
4158 /*-----------------------------------------------------------------*/
4159 static void genLabel (iCode *ic)
4160 {
4161   FENTRY;
4162
4163   /* special case never generate */
4164   if (IC_LABEL(ic) == entryLabel)
4165     return ;
4166
4167   pic16_emitpLabel(IC_LABEL(ic)->key);
4168 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4169 }
4170
4171 /*-----------------------------------------------------------------*/
4172 /* genGoto - generates a goto                                      */
4173 /*-----------------------------------------------------------------*/
4174 //tsd
4175 static void genGoto (iCode *ic)
4176 {
4177   FENTRY;
4178   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4179 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4180 }
4181
4182
4183 /*-----------------------------------------------------------------*/
4184 /* genMultbits :- multiplication of bits                           */
4185 /*-----------------------------------------------------------------*/
4186 static void genMultbits (operand *left, 
4187                          operand *right, 
4188                          operand *result)
4189 {
4190   FENTRY;
4191
4192   if(!pic16_sameRegs(AOP(result),AOP(right)))
4193     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4194
4195   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4196   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4197   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4198
4199 }
4200
4201
4202 /*-----------------------------------------------------------------*/
4203 /* genMultOneByte : 8 bit multiplication & division                */
4204 /*-----------------------------------------------------------------*/
4205 static void genMultOneByte (operand *left,
4206                             operand *right,
4207                             operand *result)
4208 {
4209
4210   FENTRY;
4211   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4212   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4213
4214   /* (if two literals, the value is computed before) */
4215   /* if one literal, literal on the right */
4216   if (AOP_TYPE(left) == AOP_LIT){
4217     operand *t = right;
4218     right = left;
4219     left = t;
4220   }
4221
4222         /* size is already checked in genMult == 1 */
4223 //      size = AOP_SIZE(result);
4224
4225         if (AOP_TYPE(right) == AOP_LIT){
4226                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4227                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4228                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4229                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4230         } else {
4231                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4232                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4233                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4234                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4235         }
4236         
4237         pic16_genMult8X8_n (left, right,result);
4238 }
4239
4240 #if 0
4241 /*-----------------------------------------------------------------*/
4242 /* genMultOneWord : 16 bit multiplication                          */
4243 /*-----------------------------------------------------------------*/
4244 static void genMultOneWord (operand *left,
4245                             operand *right,
4246                             operand *result)
4247 {
4248   FENTRY;
4249   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4250   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4251
4252   /* (if two literals, the value is computed before)
4253    * if one literal, literal on the right */
4254   if (AOP_TYPE(left) == AOP_LIT){
4255     operand *t = right;
4256     right = left;
4257     left = t;
4258   }
4259
4260   /* size is checked already == 2 */
4261 //  size = AOP_SIZE(result);
4262
4263   if (AOP_TYPE(right) == AOP_LIT) {
4264     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4265       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4266       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4267       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4268   } else {
4269     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4270       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4271       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4272       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4273   }
4274         
4275   pic16_genMult16X16_16(left, right,result);
4276 }
4277 #endif
4278
4279 #if 0
4280 /*-----------------------------------------------------------------*/
4281 /* genMultOneLong : 32 bit multiplication                          */
4282 /*-----------------------------------------------------------------*/
4283 static void genMultOneLong (operand *left,
4284                             operand *right,
4285                             operand *result)
4286 {
4287   FENTRY;
4288   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4289   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4290
4291   /* (if two literals, the value is computed before)
4292    * if one literal, literal on the right */
4293   if (AOP_TYPE(left) == AOP_LIT){
4294     operand *t = right;
4295     right = left;
4296     left = t;
4297   }
4298
4299   /* size is checked already == 4 */
4300 //  size = AOP_SIZE(result);
4301
4302   if (AOP_TYPE(right) == AOP_LIT) {
4303     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4304         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4305         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4306         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4307   } else {
4308     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4309         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4310         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4311         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4312   }
4313         
4314   pic16_genMult32X32_32(left, right,result);
4315 }
4316 #endif
4317
4318
4319
4320 /*-----------------------------------------------------------------*/
4321 /* genMult - generates code for multiplication                     */
4322 /*-----------------------------------------------------------------*/
4323 static void genMult (iCode *ic)
4324 {
4325   operand *left = IC_LEFT(ic);
4326   operand *right = IC_RIGHT(ic);
4327   operand *result= IC_RESULT(ic);   
4328
4329     FENTRY;
4330         /* assign the amsops */
4331         pic16_aopOp (left,ic,FALSE);
4332         pic16_aopOp (right,ic,FALSE);
4333         pic16_aopOp (result,ic,TRUE);
4334
4335         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4336
4337         /* special cases first *
4338         * both are bits */
4339         if (AOP_TYPE(left) == AOP_CRY
4340                 && AOP_TYPE(right)== AOP_CRY) {
4341                 genMultbits(left,right,result);
4342           goto release ;
4343         }
4344
4345         /* if both are of size == 1 */
4346         if(AOP_SIZE(left) == 1
4347                 && AOP_SIZE(right) == 1) {
4348                 genMultOneByte(left,right,result);
4349           goto release ;
4350         }
4351
4352 #if 0
4353         /* if both are of size == 2 */
4354         if(AOP_SIZE(left) == 2
4355                 && AOP_SIZE(right) == 2) {
4356                 genMultOneWord(left, right, result);
4357           goto release;
4358         }
4359         
4360         /* if both are of size == 4 */
4361         if(AOP_SIZE(left) == 4
4362                 && AOP_SIZE(right) == 4) {
4363                 genMultOneLong(left, right, result);
4364           goto release;
4365         }
4366 #endif
4367
4368         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4369         assert( !"Multiplication should have been transformed into function call!" );
4370
4371         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4372
4373
4374         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4375         /* should have been converted to function call */
4376         assert(0) ;
4377
4378 release :
4379         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4380         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4381         pic16_freeAsmop(result,NULL,ic,TRUE); 
4382 }
4383
4384 #if 0
4385 /*-----------------------------------------------------------------*/
4386 /* genDivbits :- division of bits                                  */
4387 /*-----------------------------------------------------------------*/
4388 static void genDivbits (operand *left, 
4389                         operand *right, 
4390                         operand *result)
4391 {
4392   char *l;
4393
4394     FENTRY;
4395     /* the result must be bit */    
4396     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4397     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4398
4399     MOVA(l);    
4400
4401     pic16_emitcode("div","ab");
4402     pic16_emitcode("rrc","a");
4403     pic16_aopPut(AOP(result),"c",0);
4404 }
4405
4406 /*-----------------------------------------------------------------*/
4407 /* genDivOneByte : 8 bit division                                  */
4408 /*-----------------------------------------------------------------*/
4409 static void genDivOneByte (operand *left,
4410                            operand *right,
4411                            operand *result)
4412 {
4413   sym_link *opetype = operandType(result);
4414   char *l ;
4415   symbol *lbl ;
4416   int size,offset;
4417
4418         /* result = divident / divisor
4419          * - divident may be a register or a literal,
4420          * - divisor may be a register or a literal,
4421          * so there are 3 cases (literal / literal is optimized
4422          * by the front-end) to handle.
4423          * In addition we must handle signed and unsigned, which
4424          * result in 6 final different cases -- VR */
4425
4426     FENTRY;
4427     
4428     size = AOP_SIZE(result) - 1;
4429     offset = 1;
4430     /* signed or unsigned */
4431     if (SPEC_USIGN(opetype)) {
4432       pCodeOp *pct1,    /* count */
4433                 *pct2,  /* reste */
4434                 *pct3;  /* temp */
4435       symbol *label1, *label2, *label3;;
4436
4437
4438         /* unsigned is easy */
4439
4440         pct1 = pic16_popGetTempReg(1);
4441         pct2 = pic16_popGetTempReg(1);
4442         pct3 = pic16_popGetTempReg(1);
4443         
4444         label1 = newiTempLabel(NULL);
4445         label2 = newiTempLabel(NULL);
4446         label3 = newiTempLabel(NULL);
4447
4448         /* the following algorithm is extracted from divuint.c */
4449
4450         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4451         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4452         
4453         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4454
4455         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4456         
4457         pic16_emitpLabel(label1->key);
4458         
4459         emitCLRC;
4460         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4461
4462
4463         emitCLRC;
4464         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4465         
4466
4467         emitSKPNC;
4468         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4469         
4470         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4471         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4472         
4473         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4474         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4475         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4476         
4477         pic16_emitpLabel( label3->key );
4478         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4479         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4480         
4481         
4482
4483         pic16_emitpLabel(label2->key);
4484         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4485         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4486         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4487         
4488         /* result is in wreg */
4489         if(AOP_TYPE(result) != AOP_ACC)
4490                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4491
4492         pic16_popReleaseTempReg( pct3, 1);
4493         pic16_popReleaseTempReg( pct2, 1);
4494         pic16_popReleaseTempReg( pct1, 1);
4495
4496         return ;
4497     }
4498
4499     /* signed is a little bit more difficult */
4500
4501     /* save the signs of the operands */
4502     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4503     MOVA(l);    
4504     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4505     pic16_emitcode("push","acc"); /* save it on the stack */
4506
4507     /* now sign adjust for both left & right */
4508     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4509     MOVA(l);       
4510     lbl = newiTempLabel(NULL);
4511     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4512     pic16_emitcode("cpl","a");   
4513     pic16_emitcode("inc","a");
4514     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4515     pic16_emitcode("mov","b,a");
4516
4517     /* sign adjust left side */
4518     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4519     MOVA(l);
4520
4521     lbl = newiTempLabel(NULL);
4522     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4523     pic16_emitcode("cpl","a");
4524     pic16_emitcode("inc","a");
4525     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4526
4527     /* now the division */
4528     pic16_emitcode("div","ab");
4529     /* we are interested in the lower order
4530     only */
4531     pic16_emitcode("mov","b,a");
4532     lbl = newiTempLabel(NULL);
4533     pic16_emitcode("pop","acc");   
4534     /* if there was an over flow we don't 
4535     adjust the sign of the result */
4536     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4537     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4538     CLRC;
4539     pic16_emitcode("clr","a");
4540     pic16_emitcode("subb","a,b");
4541     pic16_emitcode("mov","b,a");
4542     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4543
4544     /* now we are done */
4545     pic16_aopPut(AOP(result),"b",0);
4546     if(size > 0){
4547         pic16_emitcode("mov","c,b.7");
4548         pic16_emitcode("subb","a,acc");   
4549     }
4550     while (size--)
4551         pic16_aopPut(AOP(result),"a",offset++);
4552
4553 }
4554 #endif
4555
4556 /*-----------------------------------------------------------------*/
4557 /* genDiv - generates code for division                            */
4558 /*-----------------------------------------------------------------*/
4559 static void genDiv (iCode *ic)
4560 {
4561     operand *left = IC_LEFT(ic);
4562     operand *right = IC_RIGHT(ic);
4563     operand *result= IC_RESULT(ic);   
4564     int negated = 0;
4565     int leftVal = 0, rightVal = 0;
4566     int signedLits = 0;
4567     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4568     int op = 0;
4569     
4570         /* Division is a very lengthy algorithm, so it is better
4571          * to call support routines than inlining algorithm.
4572          * Division functions written here just in case someone
4573          * wants to inline and not use the support libraries -- VR */
4574
4575     FENTRY;
4576     
4577     /* assign the amsops */
4578     pic16_aopOp (left,ic,FALSE);
4579     pic16_aopOp (right,ic,FALSE);
4580     pic16_aopOp (result,ic,TRUE);
4581
4582     if (ic->op == '/')
4583       op = 0;
4584     else if (ic->op == '%')
4585       op = 1;
4586     else
4587       assert( !"invalid operation requested in genDivMod" );
4588
4589     /* get literal values */
4590     if (IS_VALOP(left)) {
4591       leftVal = (int)floatFromVal( OP_VALUE(left) );
4592       assert( leftVal >= -128 && leftVal < 256 );
4593       if (leftVal < 0) { signedLits++; }
4594     }
4595     if (IS_VALOP(right)) {
4596       rightVal = (int)floatFromVal( OP_VALUE(right) );
4597       assert( rightVal >= -128 && rightVal < 256 );
4598       if (rightVal < 0) { signedLits++; }
4599     }
4600
4601     /* We should only come here to convert all
4602      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4603      * with exactly one operand being s8_t into
4604      * u8_t x u8_t -> u8_t. All other cases should have been
4605      * turned into calls to support routines beforehand... */
4606     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4607         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4608     {
4609       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4610           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4611       {
4612         /* Both operands are signed or negative, use _divschar
4613          * instead of _divuchar */
4614         pushaop(AOP(right), 0);
4615         pushaop(AOP(left), 0);
4616
4617         /* call _divschar */
4618         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4619
4620         {
4621           symbol *sym;
4622           sym = newSymbol( functions[op][0], 0 );
4623           sym->used++;
4624           strcpy(sym->rname, functions[op][0]);
4625           checkAddSym(&externs, sym);
4626         }
4627
4628         /* assign result */
4629         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4630         if (AOP_SIZE(result) > 1)
4631         {
4632           pic16_emitpcode(POC_MOVFF,
4633               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4634                 pic16_popGet(AOP(result), 1)));
4635           /* sign extend */
4636           pic16_addSign(result, 2, 1);
4637         }
4638
4639         /* clean up stack */
4640         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4641         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4642
4643         goto release;
4644       }
4645       
4646       /* push right operand */
4647       if (IS_VALOP(right)) {
4648         if (rightVal < 0) {
4649           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4650           negated++;
4651         } else {
4652           pushaop(AOP(right), 0);
4653         }
4654       } else if (!IS_UNSIGNED(operandType(right))) {
4655         pic16_mov2w(AOP(right), 0);
4656         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4657         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4658         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4659         negated++;
4660       } else {
4661         pushaop(AOP(right), 0);
4662       }
4663
4664       /* push left operand */
4665       if (IS_VALOP(left)) {
4666         if (leftVal < 0) {
4667           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4668           negated++;
4669         } else {
4670           pushaop(AOP(left), 0);
4671         }
4672       } else if (!IS_UNSIGNED(operandType(left))) {
4673         pic16_mov2w(AOP(left),0);
4674         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4675         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4676         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4677         negated++;
4678       } else {
4679         pushaop(AOP(left), 0);
4680       }
4681       
4682       /* call _divuchar */
4683       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4684
4685       {
4686         symbol *sym;
4687         sym = newSymbol( functions[op][1], 0 );
4688         sym->used++;
4689         strcpy(sym->rname, functions[op][1]);
4690         checkAddSym(&externs, sym);
4691       }
4692
4693       /* Revert negation(s) from above.
4694        * This is inefficient: if both operands are negative, this
4695        * should not touch WREG. However, determining that exactly
4696        * one operand was negated costs at least 3 instructions,
4697        * so there is nothing to be gained here, is there?
4698        *
4699        * I negate WREG because either operand might share registers with
4700        * result, so assigning first might destroy an operand. */
4701       
4702       /* For the modulus operator, (a/b)*b == a shall hold.
4703        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4704        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
4705        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
4706        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
4707        * Only invert the result if the left operand is negative (sigh).
4708        */
4709       if (AOP_SIZE(result) <= 1 || !negated)
4710       {
4711         if (ic->op == '/')
4712         {
4713           if (IS_VALOP(right)) {
4714             if (rightVal < 0) {
4715               /* we negated this operand above */
4716               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4717             }
4718           } else if (!IS_UNSIGNED(operandType(right))) {
4719             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4720             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4721           }
4722         }
4723
4724         if (IS_VALOP(left)) {
4725           if (leftVal < 0) {
4726             /* we negated this operand above */
4727             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4728           }
4729         } else if (!IS_UNSIGNED(operandType(left))) {
4730           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4731           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4732         }
4733
4734         /* Move result to destination. */
4735         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4736
4737         /* Zero-extend:  no operand was signed (or result is just a byte). */
4738         pic16_addSign(result, 1, 0);
4739       } else {
4740         assert( AOP_SIZE(result) > 1 );
4741         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4742         if (ic->op == '/')
4743         {
4744           if (IS_VALOP(right)) {
4745             if (rightVal < 0) {
4746               /* we negated this operand above */
4747               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4748             }
4749           } else if (!IS_UNSIGNED(operandType(right))) {
4750             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4751             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4752           }
4753         }
4754
4755         if (IS_VALOP(left)) {
4756           if (leftVal < 0) {
4757             /* we negated this operand above */
4758             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4759           }
4760         } else if (!IS_UNSIGNED(operandType(left))) {
4761           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4762           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4763         }
4764
4765         /* Move result to destination. */
4766         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4767
4768         /* Negate result if required. */
4769         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4770         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4771
4772         /* Sign-extend. */
4773         pic16_addSign(result, 2, 1);
4774       }
4775
4776       /* clean up stack */
4777       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4778       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4779       goto release;
4780     }
4781
4782 #if 0
4783     /* special cases first */
4784     /* both are bits */
4785     if (AOP_TYPE(left) == AOP_CRY &&
4786         AOP_TYPE(right)== AOP_CRY) {
4787         genDivbits(left,right,result);
4788         goto release ;
4789     }
4790
4791     /* if both are of size == 1 */
4792     if (AOP_SIZE(left) == 1 &&
4793         AOP_SIZE(right) == 1 ) {
4794         genDivOneByte(left,right,result);
4795         goto release ;
4796     }
4797 #endif
4798
4799     /* should have been converted to function call */
4800     assert(0);
4801 release :
4802     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4803     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4804     pic16_freeAsmop(result,NULL,ic,TRUE); 
4805 }
4806
4807 #if 0
4808 /*-----------------------------------------------------------------*/
4809 /* genModbits :- modulus of bits                                   */
4810 /*-----------------------------------------------------------------*/
4811 static void genModbits (operand *left, 
4812                         operand *right, 
4813                         operand *result)
4814 {
4815   char *l;
4816
4817     FENTRY;  
4818     
4819     werror(W_POSSBUG2, __FILE__, __LINE__);
4820     /* the result must be bit */    
4821     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4822     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4823
4824     MOVA(l);       
4825
4826     pic16_emitcode("div","ab");
4827     pic16_emitcode("mov","a,b");
4828     pic16_emitcode("rrc","a");
4829     pic16_aopPut(AOP(result),"c",0);
4830 }
4831
4832 /*-----------------------------------------------------------------*/
4833 /* genModOneByte : 8 bit modulus                                   */
4834 /*-----------------------------------------------------------------*/
4835 static void genModOneByte (operand *left,
4836                            operand *right,
4837                            operand *result)
4838 {
4839   sym_link *opetype = operandType(result);
4840   char *l ;
4841   symbol *lbl ;
4842
4843     FENTRY;
4844     werror(W_POSSBUG2, __FILE__, __LINE__);
4845
4846     /* signed or unsigned */
4847     if (SPEC_USIGN(opetype)) {
4848         /* unsigned is easy */
4849         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4850         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4851         MOVA(l);    
4852         pic16_emitcode("div","ab");
4853         pic16_aopPut(AOP(result),"b",0);
4854         return ;
4855     }
4856
4857     /* signed is a little bit more difficult */
4858
4859     /* save the signs of the operands */
4860     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4861     MOVA(l);
4862
4863     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4864     pic16_emitcode("push","acc"); /* save it on the stack */
4865
4866     /* now sign adjust for both left & right */
4867     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4868     MOVA(l);
4869
4870     lbl = newiTempLabel(NULL);
4871     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4872     pic16_emitcode("cpl","a");   
4873     pic16_emitcode("inc","a");
4874     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4875     pic16_emitcode("mov","b,a"); 
4876
4877     /* sign adjust left side */
4878     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4879     MOVA(l);
4880
4881     lbl = newiTempLabel(NULL);
4882     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4883     pic16_emitcode("cpl","a");   
4884     pic16_emitcode("inc","a");
4885     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4886
4887     /* now the multiplication */
4888     pic16_emitcode("div","ab");
4889     /* we are interested in the lower order
4890     only */
4891     lbl = newiTempLabel(NULL);
4892     pic16_emitcode("pop","acc");   
4893     /* if there was an over flow we don't 
4894     adjust the sign of the result */
4895     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4896     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4897     CLRC ;
4898     pic16_emitcode("clr","a");
4899     pic16_emitcode("subb","a,b");
4900     pic16_emitcode("mov","b,a");
4901     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4902
4903     /* now we are done */
4904     pic16_aopPut(AOP(result),"b",0);
4905
4906 }
4907 #endif
4908
4909 /*-----------------------------------------------------------------*/
4910 /* genMod - generates code for division                            */
4911 /*-----------------------------------------------------------------*/
4912 static void genMod (iCode *ic)
4913 {
4914   /* Task deferred to genDiv */
4915   genDiv(ic);
4916 #if 0
4917   operand *left = IC_LEFT(ic);
4918   operand *right = IC_RIGHT(ic);
4919   operand *result= IC_RESULT(ic);  
4920
4921     FENTRY;
4922     
4923     /* assign the amsops */
4924     pic16_aopOp (left,ic,FALSE);
4925     pic16_aopOp (right,ic,FALSE);
4926     pic16_aopOp (result,ic,TRUE);
4927
4928     /* special cases first */
4929     /* both are bits */
4930     if (AOP_TYPE(left) == AOP_CRY &&
4931         AOP_TYPE(right)== AOP_CRY) {
4932         genModbits(left,right,result);
4933         goto release ;
4934     }
4935
4936     /* if both are of size == 1 */
4937     if (AOP_SIZE(left) == 1 &&
4938         AOP_SIZE(right) == 1 ) {
4939         genModOneByte(left,right,result);
4940         goto release ;
4941     }
4942
4943     /* should have been converted to function call */
4944     assert(0);
4945
4946 release :
4947     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4948     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4949     pic16_freeAsmop(result,NULL,ic,TRUE); 
4950 #endif
4951 }
4952
4953 /*-----------------------------------------------------------------*/
4954 /* genIfxJump :- will create a jump depending on the ifx           */
4955 /*-----------------------------------------------------------------*/
4956 /*
4957   note: May need to add parameter to indicate when a variable is in bit space.
4958 */
4959 static void genIfxJump (iCode *ic, char *jval)
4960 {
4961   FENTRY;
4962   
4963     /* if true label then we jump if condition
4964     supplied is true */
4965     if ( IC_TRUE(ic) ) {
4966
4967         if(strcmp(jval,"a") == 0)
4968           emitSKPZ;
4969         else if (strcmp(jval,"c") == 0)
4970           emitSKPNC;
4971         else {
4972           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4973           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4974         }
4975
4976         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4977         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4978
4979     }
4980     else {
4981         /* false label is present */
4982         if(strcmp(jval,"a") == 0)
4983           emitSKPNZ;
4984         else if (strcmp(jval,"c") == 0)
4985           emitSKPC;
4986         else {
4987           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4988           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4989         }
4990
4991         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4992         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4993
4994     }
4995
4996
4997     /* mark the icode as generated */
4998     ic->generated = 1;
4999 }
5000
5001 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5002 {
5003   FENTRY;
5004   
5005     /* if true label then we jump if condition
5006     supplied is true */
5007     if ( IC_TRUE(ic) ) {
5008       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
5009       pic16_emitpcode(POC_BTFSC, jop);
5010
5011       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5012       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5013
5014     } else {
5015       /* false label is present */
5016       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5017       pic16_emitpcode(POC_BTFSS, jop);
5018           
5019       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5020       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5021     }
5022
5023
5024     /* mark the icode as generated */
5025     ic->generated = 1;
5026 }
5027
5028 #if 0
5029 // not needed ATM
5030
5031 /*-----------------------------------------------------------------*/
5032 /* genSkip                                                         */
5033 /*-----------------------------------------------------------------*/
5034 static void genSkip(iCode *ifx,int status_bit)
5035 {
5036   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5037   if(!ifx)
5038     return;
5039
5040   if ( IC_TRUE(ifx) ) {
5041     switch(status_bit) {
5042     case 'z':
5043       emitSKPNZ;
5044       break;
5045
5046     case 'c':
5047       emitSKPNC;
5048       break;
5049
5050     case 'd':
5051       emitSKPDC;
5052       break;
5053
5054     }
5055
5056     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5057     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5058
5059   } else {
5060
5061     switch(status_bit) {
5062
5063     case 'z':
5064       emitSKPZ;
5065       break;
5066
5067     case 'c':
5068       emitSKPC;
5069       break;
5070
5071     case 'd':
5072       emitSKPDC;
5073       break;
5074     }
5075     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5076     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5077
5078   }
5079
5080 }
5081 #endif
5082
5083 /*-----------------------------------------------------------------*/
5084 /* genSkipc                                                        */
5085 /*-----------------------------------------------------------------*/
5086 static void genSkipc(resolvedIfx *rifx)
5087 {
5088   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5089   
5090   if(!rifx)
5091     return;
5092
5093   if(rifx->condition)
5094     emitSKPNC;
5095   else
5096     emitSKPC;
5097
5098   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5099   rifx->generated = 1;
5100 }
5101
5102 #if !(USE_SIMPLE_GENCMP)
5103 /*-----------------------------------------------------------------*/
5104 /* genSkipz2                                                       */
5105 /*-----------------------------------------------------------------*/
5106 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5107 {
5108   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5109   
5110   if(!rifx)
5111     return;
5112
5113   if( (rifx->condition ^ invert_condition) & 1)
5114     emitSKPZ;
5115   else
5116     emitSKPNZ;
5117
5118   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5119   rifx->generated = 1;
5120 }
5121 #endif
5122
5123 #if 0
5124 /*-----------------------------------------------------------------*/
5125 /* genSkipz                                                        */
5126 /*-----------------------------------------------------------------*/
5127 static void genSkipz(iCode *ifx, int condition)
5128 {
5129   if(!ifx)
5130     return;
5131
5132   if(condition)
5133     emitSKPNZ;
5134   else
5135     emitSKPZ;
5136
5137   if ( IC_TRUE(ifx) )
5138     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5139   else
5140     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5141
5142   if ( IC_TRUE(ifx) )
5143     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5144   else
5145     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5146
5147 }
5148 #endif
5149
5150 #if !(USE_SIMPLE_GENCMP)
5151 /*-----------------------------------------------------------------*/
5152 /* genSkipCond                                                     */
5153 /*-----------------------------------------------------------------*/
5154 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5155 {
5156   if(!rifx)
5157     return;
5158
5159   if(rifx->condition)
5160     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5161   else
5162     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5163
5164
5165   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5166   rifx->generated = 1;
5167 }
5168 #endif
5169
5170 #if 0
5171 /*-----------------------------------------------------------------*/
5172 /* genChkZeroes :- greater or less than comparison                 */
5173 /*     For each byte in a literal that is zero, inclusive or the   */
5174 /*     the corresponding byte in the operand with W                */
5175 /*     returns true if any of the bytes are zero                   */
5176 /*-----------------------------------------------------------------*/
5177 static int genChkZeroes(operand *op, int lit,  int size)
5178 {
5179
5180   int i;
5181   int flag =1;
5182
5183   while(size--) {
5184     i = (lit >> (size*8)) & 0xff;
5185
5186     if(i==0) {
5187       if(flag) 
5188         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5189       else
5190         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5191       flag = 0;
5192     }
5193   }
5194
5195   return (flag==0);
5196 }
5197 #endif
5198
5199
5200 /*-----------------------------------------------------------------*/
5201 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
5202 /*                  aop (if it's NOT a literal) or from lit (if    */
5203 /*                  aop is a literal)                              */
5204 /*-----------------------------------------------------------------*/
5205 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5206   if (aop->type == AOP_LIT) {
5207     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5208   } else {
5209     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5210   }
5211 }
5212
5213 /*-----------------------------------------------------------------*/
5214 /* genCmp :- greater or less than comparison                       */
5215 /*-----------------------------------------------------------------*/
5216
5217 #if USE_SIMPLE_GENCMP           /* { */
5218
5219 /* genCmp performs a left < right comparison, stores
5220  * the outcome in result (if != NULL) and generates
5221  * control flow code for the ifx (if != NULL).
5222  *
5223  * This version leaves in sequences like
5224  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5225  * which should be optmized by the peephole
5226  * optimizer - RN 2005-01-01 */
5227 static void genCmp (operand *left,operand *right,
5228                     operand *result, iCode *ifx, int sign)
5229 {
5230   resolvedIfx rIfx;
5231   int size;
5232   int offs;
5233   symbol *templbl;
5234   operand *dummy;
5235   unsigned long lit;
5236   unsigned long mask;
5237   int performedLt;
5238
5239   FENTRY;
5240   
5241   assert (left && right);
5242   assert (AOP_SIZE(left) == AOP_SIZE(right));
5243
5244   size = AOP_SIZE(right) - 1;
5245   mask = (0x100UL << (size*8)) - 1;
5246   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5247   performedLt = 1;
5248   templbl = NULL;
5249   lit = 0;
5250   
5251   resolveIfx (&rIfx, ifx);
5252
5253   /* handle for special cases */
5254   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5255       return;
5256
5257   /**********************************************************************
5258    * handle bits - bit compares are promoted to int compares seemingly! *
5259    **********************************************************************/
5260 #if 0
5261   // THIS IS COMPLETELY UNTESTED!
5262   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5263     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5264     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5265     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5266
5267     emitSETC;
5268     // 1 < {0,1} is false --> clear C by skipping the next instruction
5269     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5270     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5271     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5272     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5273     emitCLRC; // only skipped for left=0 && right=1
5274
5275     goto correct_result_in_carry;
5276   } // if
5277 #endif
5278
5279   /*************************************************
5280    * make sure that left is register (or the like) *
5281    *************************************************/
5282   if (!isAOP_REGlike(left)) {
5283     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5284     assert (isAOP_LIT(left));
5285     assert (isAOP_REGlike(right));
5286     // swap left and right
5287     // left < right <==> right > left <==> (right >= left + 1)
5288     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5289
5290     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5291       // MAXVALUE < right? always false
5292       if (performedLt) emitCLRC; else emitSETC;
5293       goto correct_result_in_carry;
5294     } // if
5295
5296     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5297     // that's why we handled it above.
5298     lit++;
5299
5300     dummy = left;
5301     left = right;
5302     right = dummy;
5303
5304     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5305   } else if (isAOP_LIT(right)) {
5306     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5307   } // if
5308
5309   assert (isAOP_REGlike(left)); // left must be register or the like
5310   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5311
5312   /*************************************************
5313    * special cases go here                         *
5314    *************************************************/
5315
5316   if (isAOP_LIT(right)) {
5317     if (!sign) {
5318       // unsigned comparison to a literal
5319       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5320       if (lit == 0) {
5321         // unsigned left < 0? always false
5322         if (performedLt) emitCLRC; else emitSETC;
5323         goto correct_result_in_carry;
5324       }
5325     } else {
5326       // signed comparison to a literal
5327       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5328       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5329         // signed left < 0x80000000? always false
5330         if (performedLt) emitCLRC; else emitSETC;
5331         goto correct_result_in_carry;
5332       } else if (lit == 0) {
5333         // compare left < 0; set CARRY if SIGNBIT(left) is set
5334         if (performedLt) emitSETC; else emitCLRC;
5335         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5336         if (performedLt) emitCLRC; else emitSETC;
5337         goto correct_result_in_carry;
5338       }
5339     } // if (!sign)
5340   } // right is literal
5341
5342   /*************************************************
5343    * perform a general case comparison             *
5344    * make sure we get CARRY==1 <==> left >= right  *
5345    *************************************************/
5346   // compare most significant bytes
5347   //DEBUGpc ("comparing bytes at offset %d", size);
5348   if (!sign) {
5349     // unsigned comparison
5350     mov2w_regOrLit (AOP(right), lit, size);
5351     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5352   } else {
5353     // signed comparison
5354     // (add 2^n to both operands then perform an unsigned comparison)
5355     if (isAOP_LIT(right)) {
5356       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5357       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5358
5359       if (litbyte == 0x80) {
5360         // left >= 0x80 -- always true, but more bytes to come
5361         pic16_mov2w (AOP(left), size);
5362         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5363         emitSETC;
5364       } else {
5365         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5366         pic16_mov2w (AOP(left), size);
5367         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5368         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5369       } // if
5370     } else {
5371       /* using PRODL as a temporary register here */
5372       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5373       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5374       pic16_mov2w (AOP(left), size);
5375       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5376       pic16_emitpcode (POC_MOVWF, pctemp);
5377       pic16_mov2w (AOP(right), size);
5378       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5379       pic16_emitpcode (POC_SUBFW, pctemp);
5380       //pic16_popReleaseTempReg(pctemp, 1);
5381     }
5382   } // if (!sign)
5383
5384   // compare remaining bytes (treat as unsigned case from above)
5385   templbl = newiTempLabel ( NULL );
5386   offs = size;
5387   while (offs--) {
5388     //DEBUGpc ("comparing bytes at offset %d", offs);
5389     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5390     mov2w_regOrLit (AOP(right), lit, offs);
5391     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5392   } // while (offs)
5393   pic16_emitpLabel (templbl->key);
5394   goto result_in_carry;
5395
5396 result_in_carry:
5397   
5398   /****************************************************
5399    * now CARRY contains the result of the comparison: *
5400    * SUBWF sets CARRY iff                             *
5401    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5402    * (F=left, W=right)                                *
5403    ****************************************************/
5404
5405   if (performedLt) {
5406     if (result && AOP_TYPE(result) != AOP_CRY) {
5407       // value will be stored
5408       emitTOGC;
5409     } else {
5410       // value wil only be used in the following genSkipc()
5411       rIfx.condition ^= 1;
5412     }
5413   } // if
5414
5415 correct_result_in_carry:
5416
5417   // assign result to variable (if neccessary)
5418   if (result && AOP_TYPE(result) != AOP_CRY) {
5419     //DEBUGpc ("assign result");
5420     size = AOP_SIZE(result);
5421     while (size--) {
5422       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5423     } // while
5424     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5425   } // if (result)
5426
5427   // perform conditional jump
5428   if (ifx) {
5429     //DEBUGpc ("generate control flow");
5430     genSkipc (&rIfx);
5431     ifx->generated = 1;
5432   } // if
5433 }
5434
5435 #elif 1         /* } */
5436                 /* { */
5437       /* original code */
5438 static void genCmp (operand *left,operand *right,
5439                     operand *result, iCode *ifx, int sign)
5440 {
5441   int size; //, offset = 0 ;
5442   unsigned long lit = 0L,i = 0;
5443   resolvedIfx rFalseIfx;
5444   //  resolvedIfx rTrueIfx;
5445   symbol *truelbl;
5446   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5447 /*
5448   if(ifx) {
5449     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5450     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5451   }
5452 */
5453
5454   FENTRY;
5455   
5456   resolveIfx(&rFalseIfx,ifx);
5457   truelbl  = newiTempLabel(NULL);
5458   size = max(AOP_SIZE(left),AOP_SIZE(right));
5459
5460   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5461
5462 #define _swapp
5463
5464   /* if literal is on the right then swap with left */
5465   if ((AOP_TYPE(right) == AOP_LIT)) {
5466     operand *tmp = right ;
5467     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5468     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5469 #ifdef _swapp
5470
5471     lit = (lit - 1) & mask;
5472     right = left;
5473     left = tmp;
5474     rFalseIfx.condition ^= 1;
5475 #endif
5476
5477   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5478     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5479   }
5480
5481
5482   //if(IC_TRUE(ifx) == NULL)
5483   /* if left & right are bit variables */
5484   if (AOP_TYPE(left) == AOP_CRY &&
5485       AOP_TYPE(right) == AOP_CRY ) {
5486     assert (0 && "bit variables used in genCmp");
5487     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5488     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5489   } else {
5490     /* subtract right from left if at the
5491        end the carry flag is set then we know that
5492        left is greater than right */
5493
5494     symbol *lbl  = newiTempLabel(NULL);
5495
5496 #if 0
5497         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5498                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5499 #endif
5500
5501 #ifndef _swapp
5502     if(AOP_TYPE(right) == AOP_LIT) {
5503
5504       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5505
5506       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5507
5508       /* special cases */
5509
5510       if(lit == 0) {
5511
5512         if(sign != 0) 
5513           genSkipCond(&rFalseIfx,left,size-1,7);
5514         else 
5515           /* no need to compare to 0...*/
5516           /* NOTE: this is a de-generate compare that most certainly 
5517            *       creates some dead code. */
5518           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5519
5520         if(ifx) ifx->generated = 1;
5521         return;
5522
5523       }
5524       size--;
5525
5526       if(size == 0) {
5527         //i = (lit >> (size*8)) & 0xff;
5528         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5529         
5530         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5531
5532         i = ((0-lit) & 0xff);
5533         if(sign) {
5534           if( i == 0x81) { 
5535             /* lit is 0x7f, all signed chars are less than
5536              * this except for 0x7f itself */
5537             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5538             genSkipz2(&rFalseIfx,0);
5539           } else {
5540             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5541             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5542             genSkipc(&rFalseIfx);
5543           }
5544
5545         } else {
5546           if(lit == 1) {
5547             genSkipz2(&rFalseIfx,1);
5548           } else {
5549             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5550             genSkipc(&rFalseIfx);
5551           }
5552         }
5553
5554         if(ifx) ifx->generated = 1;
5555         return;
5556       }
5557
5558       /* chars are out of the way. now do ints and longs */
5559
5560
5561       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5562         
5563       /* special cases */
5564
5565       if(sign) {
5566
5567         if(lit == 0) {
5568           genSkipCond(&rFalseIfx,left,size,7);
5569           if(ifx) ifx->generated = 1;
5570           return;
5571         }
5572
5573         if(lit <0x100) {
5574           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5575
5576           //rFalseIfx.condition ^= 1;
5577           //genSkipCond(&rFalseIfx,left,size,7);
5578           //rFalseIfx.condition ^= 1;
5579
5580           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5581           if(rFalseIfx.condition)
5582             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5583           else
5584             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5585
5586           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5587           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5588           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5589
5590           while(size > 1)
5591             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5592
5593           if(rFalseIfx.condition) {
5594             emitSKPZ;
5595             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5596
5597           } else {
5598             emitSKPNZ;
5599           }
5600
5601           genSkipc(&rFalseIfx);
5602           pic16_emitpLabel(truelbl->key);
5603           if(ifx) ifx->generated = 1;
5604           return;
5605
5606         }
5607
5608         if(size == 1) {
5609
5610           if( (lit & 0xff) == 0) {
5611             /* lower byte is zero */
5612             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5613             i = ((lit >> 8) & 0xff) ^0x80;
5614             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5615             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5616             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5617             genSkipc(&rFalseIfx);
5618
5619
5620             if(ifx) ifx->generated = 1;
5621             return;
5622
5623           }
5624         } else {
5625           /* Special cases for signed longs */
5626           if( (lit & 0xffffff) == 0) {
5627             /* lower byte is zero */
5628             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5629             i = ((lit >> 8*3) & 0xff) ^0x80;
5630             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5631             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5632             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5633             genSkipc(&rFalseIfx);
5634
5635
5636             if(ifx) ifx->generated = 1;
5637             return;
5638
5639           }
5640
5641         }
5642
5643
5644         if(lit & (0x80 << (size*8))) {
5645           /* lit is negative */
5646           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5647
5648           //genSkipCond(&rFalseIfx,left,size,7);
5649
5650           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5651
5652           if(rFalseIfx.condition)
5653             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5654           else
5655             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5656
5657
5658         } else {
5659           /* lit is positive */
5660           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5661           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5662           if(rFalseIfx.condition)
5663             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5664           else
5665             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5666
5667         }
5668
5669         /*
5670           This works, but is only good for ints.
5671           It also requires a "known zero" register.
5672           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5673           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5674           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5675           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5676           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5677           genSkipc(&rFalseIfx);
5678
5679           pic16_emitpLabel(truelbl->key);
5680           if(ifx) ifx->generated = 1;
5681           return;
5682         **/
5683           
5684         /* There are no more special cases, so perform a general compare */
5685   
5686         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5687         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5688
5689         while(size--) {
5690
5691           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5692           emitSKPNZ;
5693           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5694         }
5695         //rFalseIfx.condition ^= 1;
5696         genSkipc(&rFalseIfx);
5697
5698         pic16_emitpLabel(truelbl->key);
5699
5700         if(ifx) ifx->generated = 1;
5701         return;
5702
5703
5704       }
5705
5706
5707       /* sign is out of the way. So now do an unsigned compare */
5708       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5709
5710
5711       /* General case - compare to an unsigned literal on the right.*/
5712
5713       i = (lit >> (size*8)) & 0xff;
5714       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5715       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5716       while(size--) {
5717         i = (lit >> (size*8)) & 0xff;
5718
5719         if(i) {
5720           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5721           emitSKPNZ;
5722           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5723         } else {
5724           /* this byte of the lit is zero, 
5725            *if it's not the last then OR in the variable */
5726           if(size)
5727             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5728         }
5729       }
5730
5731
5732       pic16_emitpLabel(lbl->key);
5733 //      pic16_emitpLabel(truelbl->key);
5734       //if(emitFinalCheck)
5735       genSkipc(&rFalseIfx);
5736       if(sign)
5737         pic16_emitpLabel(truelbl->key);
5738
5739       if(ifx) ifx->generated = 1;
5740       return;
5741
5742
5743     }
5744 #endif  // _swapp
5745
5746     if(AOP_TYPE(left) == AOP_LIT) {
5747       //symbol *lbl = newiTempLabel(NULL);
5748
5749       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5750
5751
5752       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5753
5754       /* Special cases */
5755       if((lit == 0) && (sign == 0)){
5756
5757         size--;
5758         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5759         while(size) 
5760           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5761
5762         genSkipz2(&rFalseIfx,0);
5763         if(ifx) ifx->generated = 1;
5764         return;
5765       }
5766
5767       if(size==1) {
5768         /* Special cases */
5769         lit &= 0xff;
5770         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5771           /* degenerate compare can never be true */
5772           if(rFalseIfx.condition == 0)
5773             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5774
5775           if(ifx) ifx->generated = 1;
5776           return;
5777         }
5778
5779         if(sign) {
5780           /* signed comparisons to a literal byte */
5781
5782           int lp1 = (lit+1) & 0xff;
5783
5784           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5785           switch (lp1) {
5786           case 0:
5787             rFalseIfx.condition ^= 1;
5788             genSkipCond(&rFalseIfx,right,0,7);
5789             break;
5790           case 0x7f:
5791             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5792             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5793             genSkipz2(&rFalseIfx,1);
5794             break;
5795           default:
5796             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5797             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5798             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5799             rFalseIfx.condition ^= 1;
5800             genSkipc(&rFalseIfx);
5801             break;
5802           }
5803         } else {
5804           /* unsigned comparisons to a literal byte */
5805
5806           switch(lit & 0xff ) {
5807           case 0:
5808             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5809             genSkipz2(&rFalseIfx,0);
5810             break;
5811           case 0x7f:
5812             rFalseIfx.condition ^= 1;
5813             genSkipCond(&rFalseIfx,right,0,7);
5814             break;
5815
5816           default:
5817             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5818             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5819             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5820             rFalseIfx.condition ^= 1;
5821             if (AOP_TYPE(result) == AOP_CRY)
5822               genSkipc(&rFalseIfx);
5823             else {
5824               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5825               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5826             }         
5827             break;
5828           }
5829         }
5830
5831         if(ifx) ifx->generated = 1;
5832         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5833                 goto check_carry;
5834         return;
5835
5836       } else {
5837
5838         /* Size is greater than 1 */
5839
5840         if(sign) {
5841           int lp1 = lit+1;
5842
5843           size--;
5844
5845           if(lp1 == 0) {
5846             /* this means lit = 0xffffffff, or -1 */
5847
5848
5849             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5850             rFalseIfx.condition ^= 1;
5851             genSkipCond(&rFalseIfx,right,size,7);
5852             if(ifx) ifx->generated = 1;
5853
5854             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5855               goto check_carry;
5856
5857             return;
5858           }
5859
5860           if(lit == 0) {
5861             int s = size;
5862
5863             if(rFalseIfx.condition) {
5864               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5865               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5866             }
5867
5868             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5869             while(size--)
5870               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5871
5872
5873             emitSKPZ;
5874             if(rFalseIfx.condition) {
5875               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5876               pic16_emitpLabel(truelbl->key);
5877             }else {
5878               rFalseIfx.condition ^= 1;
5879               genSkipCond(&rFalseIfx,right,s,7);
5880             }
5881
5882             if(ifx) ifx->generated = 1;
5883
5884             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5885               goto check_carry;
5886
5887             return;
5888           }
5889
5890           if((size == 1) &&  (0 == (lp1&0xff))) {
5891             /* lower byte of signed word is zero */
5892             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5893             i = ((lp1 >> 8) & 0xff) ^0x80;
5894             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5895             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5896             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5897
5898             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5899               emitTOGC;
5900               if(ifx) ifx->generated = 1;
5901               goto check_carry;
5902             } else {
5903               rFalseIfx.condition ^= 1;
5904               genSkipc(&rFalseIfx);
5905               if(ifx) ifx->generated = 1;
5906             }
5907
5908             return;
5909           }
5910
5911           if(lit & (0x80 << (size*8))) {
5912             /* Lit is less than zero */
5913             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5914             //rFalseIfx.condition ^= 1;
5915             //genSkipCond(&rFalseIfx,left,size,7);
5916             //rFalseIfx.condition ^= 1;
5917             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5918             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5919
5920             if(rFalseIfx.condition)
5921               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5922             else
5923               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5924
5925
5926           } else {
5927             /* Lit is greater than or equal to zero */
5928             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5929             //rFalseIfx.condition ^= 1;
5930             //genSkipCond(&rFalseIfx,right,size,7);
5931             //rFalseIfx.condition ^= 1;
5932
5933             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5934             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5935
5936             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5937             if(rFalseIfx.condition)
5938               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5939             else
5940               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5941
5942           }
5943
5944           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5945           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5946
5947           while(size--) {
5948
5949             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5950             emitSKPNZ;
5951             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5952           }
5953           rFalseIfx.condition ^= 1;
5954           //rFalseIfx.condition = 1;
5955           genSkipc(&rFalseIfx);
5956
5957           pic16_emitpLabel(truelbl->key);
5958
5959           if(ifx) ifx->generated = 1;
5960
5961
5962           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5963             goto check_carry;
5964
5965           return;
5966           // end of if (sign)
5967         } else {
5968
5969           /* compare word or long to an unsigned literal on the right.*/
5970
5971
5972           size--;
5973           if(lit < 0xff) {
5974             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5975             switch (lit) {
5976             case 0:
5977               break; /* handled above */
5978 /*
5979             case 0xff:
5980               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5981               while(size--)
5982                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5983               genSkipz2(&rFalseIfx,0);
5984               break;
5985 */
5986             default:
5987               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5988               while(--size)
5989                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5990
5991               emitSKPZ;
5992               if(rFalseIfx.condition)
5993                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5994               else
5995                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5996
5997
5998               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5999               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6000
6001               rFalseIfx.condition ^= 1;
6002               genSkipc(&rFalseIfx);
6003             }
6004
6005             pic16_emitpLabel(truelbl->key);
6006
6007             if(ifx) ifx->generated = 1;
6008
6009             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6010               goto check_carry;
6011
6012             return;
6013           }
6014
6015
6016           lit++;
6017           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6018           i = (lit >> (size*8)) & 0xff;
6019
6020           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6021           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6022
6023           while(size--) {
6024             i = (lit >> (size*8)) & 0xff;
6025
6026             if(i) {
6027               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6028               emitSKPNZ;
6029               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6030             } else {
6031               /* this byte of the lit is zero, 
6032                * if it's not the last then OR in the variable */
6033               if(size)
6034                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6035             }
6036           }
6037
6038
6039           pic16_emitpLabel(lbl->key);
6040
6041           rFalseIfx.condition ^= 1;
6042
6043           genSkipc(&rFalseIfx);
6044         }
6045
6046         if(sign)
6047           pic16_emitpLabel(truelbl->key);
6048         if(ifx) ifx->generated = 1;
6049
6050             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6051               goto check_carry;
6052
6053         return;
6054       }
6055     }
6056     /* Compare two variables */
6057
6058     DEBUGpic16_emitcode(";sign","%d",sign);
6059
6060     size--;
6061     if(sign) {
6062       /* Sigh. thus sucks... */
6063       if(size) {
6064         pCodeOp *pctemp;
6065         
6066         pctemp = pic16_popGetTempReg(1);
6067         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6068         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6069         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6070         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6071         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6072         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6073         pic16_popReleaseTempReg(pctemp, 1);
6074       } else {
6075         /* Signed char comparison */
6076         /* Special thanks to Nikolai Golovchenko for this snippet */
6077         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6078         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6079         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6080         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6081         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6082         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6083
6084         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6085         genSkipc(&rFalseIfx);
6086           
6087         if(ifx) ifx->generated = 1;
6088
6089             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6090               goto check_carry;
6091
6092         return;
6093       }
6094
6095     } else {
6096
6097       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6098       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6099     }
6100
6101
6102     /* The rest of the bytes of a multi-byte compare */
6103     while (size) {
6104
6105       emitSKPZ;
6106       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6107       size--;
6108
6109       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6110       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6111
6112
6113     }
6114
6115     pic16_emitpLabel(lbl->key);
6116
6117     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6118     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6119         (AOP_TYPE(result) == AOP_REG)) {
6120       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6121       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6122     } else {
6123       genSkipc(&rFalseIfx);
6124     }         
6125     //genSkipc(&rFalseIfx);
6126     if(ifx) ifx->generated = 1;
6127
6128
6129             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6130               goto check_carry;
6131
6132     return;
6133
6134   }
6135
6136 check_carry:
6137   if ((AOP_TYPE(result) != AOP_CRY) 
6138         && AOP_SIZE(result)) {
6139     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6140
6141     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6142
6143     pic16_outBitC(result);
6144   } else {
6145     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6146     /* if the result is used in the next
6147        ifx conditional branch then generate
6148        code a little differently */
6149     if (ifx )
6150       genIfxJump (ifx,"c");
6151     else
6152       pic16_outBitC(result);
6153     /* leave the result in acc */
6154   }
6155
6156 }
6157
6158 #elif 0 /* VR version of genCmp() */    /* } else { */
6159
6160 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6161 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6162         operand *result, int offset, int invert_op)
6163 {
6164   /* add code here */
6165   
6166   /* check condition, > or < ?? */
6167   if(rIfx->condition != 0)invert_op ^= 1;
6168   
6169   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6170
6171   if(!ifx)invert_op ^= 1;
6172
6173   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6174       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6175   
6176   /* do selection */
6177   if(!invert_op)return POC_CPFSGT;
6178   else return POC_CPFSLT;
6179 }
6180
6181 static int compareAopfirstpass=1;
6182
6183 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6184             operand *oper, int offset, operand *result,
6185             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6186             symbol *tlbl)
6187 {
6188   int op;
6189   symbol *truelbl;
6190
6191   /* invert if there is a result to be loaded, in order to fit,
6192    * SETC/CLRC sequence */
6193   if(AOP_SIZE(result))invert_op ^= 1;
6194
6195 //  if(sign && !offset)invert_op ^= 1;
6196   
6197 //  if(sign)invert_op ^= 1;
6198   
6199   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6200
6201   if(AOP_SIZE(result) && compareAopfirstpass) {
6202     if(!ifx) {
6203       if(pcop2)
6204         pic16_emitpcode(POC_SETF, pcop2);
6205       else
6206         emitSETC;
6207     } else {
6208       if(pcop2)
6209         pic16_emitpcode(POC_CLRF, pcop2);
6210       else
6211         emitCLRC;
6212     }
6213   }
6214
6215   compareAopfirstpass = 0;
6216
6217       /* there is a bug when comparing operands with size > 1,
6218        * because higher bytes can be equal and test should be performed
6219        * to the next lower byte, current algorithm, considers operands
6220        * inequal in these cases! -- VR 20041107 */
6221
6222     
6223   if(pcop)
6224     pic16_emitpcode(op, pcop);
6225   else
6226     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6227
6228
6229   if((!sign || !offset) && AOP_SIZE(result)) {
6230     if(!ifx) {
6231       if(pcop2)
6232         pic16_emitpcode(POC_CLRF, pcop2);
6233         else
6234         emitCLRC;
6235     } else {
6236       if(pcop2)
6237         pic16_emitpcode(POC_SETF, pcop2);
6238       else
6239         emitSETC;
6240     }
6241     
6242     /* don't emit final branch (offset == 0) */
6243     if(offset) {
6244
6245       if(pcop2)
6246         pic16_emitpcode(POC_RRCF, pcop2);
6247
6248       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6249     }
6250   } else {
6251     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6252       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6253             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6254
6255       truelbl = newiTempLabel( NULL );
6256       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6257       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6258         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6259       else
6260         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6261       pic16_emitpLabel(truelbl->key);
6262     } else {
6263       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6264     }
6265   }
6266 }
6267
6268 static void genCmp (operand *left, operand *right,
6269                     operand *result, iCode *ifx, int sign)
6270 {
6271   int size, cmpop=1;
6272   long lit = 0L;
6273   resolvedIfx rFalseIfx;
6274   symbol *falselbl, *tlbl;
6275
6276     FENTRY;
6277     
6278     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6279
6280     resolveIfx(&rFalseIfx, ifx);
6281     size = max(AOP_SIZE(left), AOP_SIZE(right));
6282     
6283     /* if left & right are bit variables */
6284     if(AOP_TYPE(left) == AOP_CRY
6285       && AOP_TYPE(right) == AOP_CRY ) {
6286
6287         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6288         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6289         
6290         werror(W_POSSBUG2, __FILE__, __LINE__);
6291         exit(EXIT_FAILURE);
6292     }
6293     
6294     /* if literal is on the right then swap with left */
6295     if((AOP_TYPE(right) == AOP_LIT)) {
6296       operand *tmp = right ;
6297 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6298
6299         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6300
6301 //      lit = (lit - 1) & mask;
6302         right = left;
6303         left = tmp;
6304         rFalseIfx.condition ^= 1;               /* reverse compare */
6305     } else
6306     if ((AOP_TYPE(left) == AOP_LIT)) {
6307       /* float compares are handled by support functions */
6308       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6309     }
6310
6311     /* actual comparing algorithm */
6312 //    size = AOP_SIZE( right );
6313
6314     falselbl = newiTempLabel( NULL );
6315     if(AOP_TYPE(left) == AOP_LIT) {
6316       /* compare to literal */
6317       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6318       
6319       if(sign) {
6320         pCodeOp *pct, *pct2;
6321         symbol *tlbl1;
6322
6323         /* signed compare */
6324         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6325
6326         /* using PRODL:PRODH as a temporary register here */
6327         pct = pic16_popCopyReg(&pic16_pc_prodl);
6328         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6329         tlbl = newiTempLabel( NULL );
6330         
6331         /* first compare signs:
6332          *  a. if both are positive, compare just like unsigned
6333          *  b. if both are negative, invert cmpop, compare just like unsigned
6334          *  c. if different signs, determine the result directly */
6335
6336         size--;
6337
6338 #if 1
6339         /* { */
6340         tlbl1 = newiTempLabel( NULL );
6341 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6342
6343         if(lit > 0) {
6344
6345           /* literal is zero or positive:
6346            *  a. if carry is zero, too, continue compare,
6347            *  b. if carry is set, then continue depending on cmpop ^ condition:
6348            *    1. '<' return false (literal < variable),
6349            *    2. '>' return true (literal > variable) */
6350 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6351           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6352           
6353           
6354           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6355           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6356         } else 
6357         if(lit < 0) {
6358           
6359           /* literal is negative:
6360            *  a. if carry is set, too, continue compare,
6361            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6362            *    1. '<' return true (literal < variable),
6363            *    2. '>' return false (literal > variable) */
6364 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6365           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6366           
6367           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6368           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6369         }
6370 #if 1
6371         else {
6372           /* lit == 0 */
6373           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6374           
6375           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6376           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6377         }
6378 #endif
6379         
6380         
6381         pic16_emitpLabel( tlbl1->key );
6382 #endif  /* } */
6383
6384         compareAopfirstpass=1;
6385 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6386 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6387 //        pic16_emitpcode(POC_MOVWF, pct);
6388
6389 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6390         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6391 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6392         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6393
6394         /* generic case */        
6395           while( size-- ) {
6396 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6397 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6398 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6399 //            pic16_emitpcode(POC_MOVWF, pct);
6400
6401 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6402             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6403             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6404 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6405 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6406           }
6407         
6408         if(ifx)ifx->generated = 1;
6409
6410         if(AOP_SIZE(result)) {
6411           pic16_emitpLabel(tlbl->key);
6412           pic16_emitpLabel(falselbl->key);
6413           pic16_outBitOp( result, pct2 );
6414         } else {
6415           pic16_emitpLabel(tlbl->key);
6416         }
6417       } else {
6418
6419         /* unsigned compare */      
6420         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6421     
6422         compareAopfirstpass=1;
6423         while(size--) {
6424           
6425           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6426           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6427
6428         }
6429         if(ifx)ifx->generated = 1;
6430
6431         if(AOP_SIZE(result)) {
6432           pic16_emitpLabel(falselbl->key);
6433           pic16_outBitC( result );
6434         }
6435
6436       }
6437     } else {
6438       /* compare registers */
6439       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6440
6441
6442       if(sign) {
6443         pCodeOp *pct, *pct2;
6444         
6445         /* signed compare */
6446         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6447
6448         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6449         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6450         tlbl = newiTempLabel( NULL );
6451         
6452         compareAopfirstpass=1;
6453
6454         size--;
6455         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6456 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6457         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6458         pic16_emitpcode(POC_MOVWF, pct);
6459
6460         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6461 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6462         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6463
6464         /* WREG already holds left + 0x80 */
6465         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6466         
6467         while( size-- ) {
6468           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6469 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6470           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6471           pic16_emitpcode(POC_MOVWF, pct);
6472                 
6473           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6474 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6475           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6476
6477           /* WREG already holds left + 0x80 */
6478           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6479 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6480         }
6481         
6482         if(ifx)ifx->generated = 1;
6483
6484         if(AOP_SIZE(result)) {
6485           pic16_emitpLabel(tlbl->key);
6486           pic16_emitpLabel(falselbl->key);
6487           pic16_outBitOp( result, pct2 );
6488         } else {
6489           pic16_emitpLabel(tlbl->key);
6490         }
6491
6492       } else {
6493         /* unsigned compare */      
6494         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6495
6496         compareAopfirstpass=1;
6497         while(size--) {
6498           
6499           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6500           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6501
6502         }
6503
6504         if(ifx)ifx->generated = 1;
6505         if(AOP_SIZE(result)) {
6506
6507           pic16_emitpLabel(falselbl->key);
6508           pic16_outBitC( result );
6509         }
6510
6511       }
6512     }
6513 }
6514
6515 #endif  /* } */
6516
6517
6518
6519 /*-----------------------------------------------------------------*/
6520 /* genCmpGt :- greater than comparison                             */
6521 /*-----------------------------------------------------------------*/
6522 static void genCmpGt (iCode *ic, iCode *ifx)
6523 {
6524   operand *left, *right, *result;
6525   sym_link *letype , *retype;
6526   int sign ;
6527
6528     FENTRY;
6529     
6530     left = IC_LEFT(ic);
6531     right= IC_RIGHT(ic);
6532     result = IC_RESULT(ic);
6533
6534     letype = getSpec(operandType(left));
6535     retype =getSpec(operandType(right));
6536     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6537     /* assign the amsops */
6538     pic16_aopOp (left,ic,FALSE);
6539     pic16_aopOp (right,ic,FALSE);
6540     pic16_aopOp (result,ic,TRUE);
6541
6542     genCmp(right, left, result, ifx, sign);
6543
6544     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6545     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6546     pic16_freeAsmop(result,NULL,ic,TRUE); 
6547 }
6548
6549 /*-----------------------------------------------------------------*/
6550 /* genCmpLt - less than comparisons                                */
6551 /*-----------------------------------------------------------------*/
6552 static void genCmpLt (iCode *ic, iCode *ifx)
6553 {
6554   operand *left, *right, *result;
6555   sym_link *letype , *retype;
6556   int sign ;
6557
6558     FENTRY;
6559
6560     left = IC_LEFT(ic);
6561     right= IC_RIGHT(ic);
6562     result = IC_RESULT(ic);
6563
6564     letype = getSpec(operandType(left));
6565     retype =getSpec(operandType(right));
6566     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6567
6568     /* assign the amsops */
6569     pic16_aopOp (left,ic,FALSE);
6570     pic16_aopOp (right,ic,FALSE);
6571     pic16_aopOp (result,ic,TRUE);
6572
6573     genCmp(left, right, result, ifx, sign);
6574
6575     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6576     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6577     pic16_freeAsmop(result,NULL,ic,TRUE); 
6578 }
6579
6580 #if 0
6581 // not needed ATM
6582 // FIXME reenable literal optimisation when the pic16 port is stable
6583
6584 /*-----------------------------------------------------------------*/
6585 /* genc16bit2lit - compare a 16 bit value to a literal             */
6586 /*-----------------------------------------------------------------*/
6587 static void genc16bit2lit(operand *op, int lit, int offset)
6588 {
6589   int i;
6590
6591   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6592   if( (lit&0xff) == 0) 
6593     i=1;
6594   else
6595     i=0;
6596
6597   switch( BYTEofLONG(lit,i)) { 
6598   case 0:
6599     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6600     break;
6601   case 1:
6602     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6603     break;
6604   case 0xff:
6605     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6606     break;
6607   default:
6608     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6609     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6610   }
6611
6612   i ^= 1;
6613
6614   switch( BYTEofLONG(lit,i)) { 
6615   case 0:
6616     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6617     break;
6618   case 1:
6619     emitSKPNZ;
6620     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6621     break;
6622   case 0xff:
6623     emitSKPNZ;
6624     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6625     break;
6626   default:
6627     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6628     emitSKPNZ;
6629     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6630
6631   }
6632
6633 }
6634 #endif
6635
6636 #if 0
6637 // not needed ATM
6638 /*-----------------------------------------------------------------*/
6639 /* gencjneshort - compare and jump if not equal                    */
6640 /*-----------------------------------------------------------------*/
6641 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6642 {
6643   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6644   int offset = 0;
6645   int res_offset = 0;  /* the result may be a different size then left or right */
6646   int res_size = AOP_SIZE(result);
6647   resolvedIfx rIfx;
6648   symbol *lbl, *lbl_done;
6649
6650   unsigned long lit = 0L;
6651   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6652
6653   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6654   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6655   if(result)
6656     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6657   resolveIfx(&rIfx,ifx);
6658   lbl =  newiTempLabel(NULL);
6659   lbl_done =  newiTempLabel(NULL);
6660
6661
6662   /* if the left side is a literal or 
6663      if the right is in a pointer register and left 
6664      is not */
6665   if ((AOP_TYPE(left) == AOP_LIT) || 
6666       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6667     operand *t = right;
6668     right = left;
6669     left = t;
6670   }
6671   if(AOP_TYPE(right) == AOP_LIT)
6672     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6673
6674   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6675     preserve_result = 1;
6676
6677   if(result && !preserve_result)
6678     {
6679       int i;
6680       for(i = 0; i < AOP_SIZE(result); i++)
6681         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6682     }
6683
6684
6685   /* if the right side is a literal then anything goes */
6686   if (AOP_TYPE(right) == AOP_LIT &&
6687       AOP_TYPE(left) != AOP_DIR ) {
6688     switch(size) {
6689     case 2:
6690       genc16bit2lit(left, lit, 0);
6691       emitSKPZ;
6692       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6693       break;
6694     default:
6695       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6696       while (size--) {
6697         if(lit & 0xff) {
6698           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6699           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6700         } else {
6701           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6702         }
6703
6704         emitSKPZ;
6705         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6706         offset++;
6707         if(res_offset < res_size-1)
6708           res_offset++;
6709         lit >>= 8;
6710       }
6711       break;
6712     }
6713   }
6714
6715   /* if the right side is in a register or in direct space or
6716      if the left is a pointer register & right is not */    
6717   else if (AOP_TYPE(right) == AOP_REG ||
6718            AOP_TYPE(right) == AOP_DIR || 
6719            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6720            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6721     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6722     int lbl_key = lbl->key;
6723
6724     if(result) {
6725       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6726       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6727     }else {
6728       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6729       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6730               __FUNCTION__,__LINE__);
6731       return;
6732     }
6733    
6734 /*     switch(size) { */
6735 /*     case 2: */
6736 /*       genc16bit2lit(left, lit, 0); */
6737 /*       emitSKPNZ; */
6738 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6739 /*       break; */
6740 /*     default: */
6741     while (size--) {
6742       int emit_skip=1;
6743       if((AOP_TYPE(left) == AOP_DIR) && 
6744          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6745
6746         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6747         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6748
6749       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6750             
6751         switch (lit & 0xff) {
6752         case 0:
6753           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6754           break;
6755         case 1:
6756           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6757           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6758           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6759           emit_skip=0;
6760           break;
6761         case 0xff:
6762           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6763           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6764           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6765           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6766           emit_skip=0;
6767           break;
6768         default:
6769           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6770           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6771         }
6772         lit >>= 8;
6773
6774       } else {
6775         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6776       }
6777       if(emit_skip) {
6778         if(AOP_TYPE(result) == AOP_CRY) {
6779           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6780           if(rIfx.condition)
6781             emitSKPNZ;
6782           else
6783             emitSKPZ;
6784           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6785         } else {
6786           /* fix me. probably need to check result size too */
6787           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6788           if(rIfx.condition)
6789             emitSKPZ;
6790           else
6791             emitSKPNZ;
6792           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6793           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6794         }
6795         if(ifx)
6796           ifx->generated=1;
6797       }
6798       emit_skip++;
6799       offset++;
6800       if(res_offset < res_size-1)
6801         res_offset++;
6802     }
6803 /*       break; */
6804 /*     } */
6805   } else if(AOP_TYPE(right) == AOP_REG &&
6806             AOP_TYPE(left) != AOP_DIR){
6807
6808     while(size--) {
6809       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6810       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6811       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6812       if(rIfx.condition)
6813         emitSKPNZ;
6814       else
6815         emitSKPZ;
6816       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6817       offset++;
6818       if(res_offset < res_size-1)
6819         res_offset++;
6820     }
6821       
6822   }else{
6823     /* right is a pointer reg need both a & b */
6824     while(size--) {
6825       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6826       if(strcmp(l,"b"))
6827         pic16_emitcode("mov","b,%s",l);
6828       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6829       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6830       offset++;
6831     }
6832   }
6833
6834   if(result && preserve_result)
6835     {
6836       int i;
6837       for(i = 0; i < AOP_SIZE(result); i++)
6838         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6839     }
6840
6841   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6842
6843   if(result && preserve_result)
6844     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6845
6846   if(!rIfx.condition)
6847     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6848
6849   pic16_emitpLabel(lbl->key);
6850
6851   if(result && preserve_result)
6852     {
6853       int i;
6854       for(i = 0; i < AOP_SIZE(result); i++)
6855         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6856
6857       pic16_emitpLabel(lbl_done->key);
6858    }
6859
6860   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6861
6862   if(ifx)
6863     ifx->generated = 1;
6864 }
6865 #endif
6866
6867 #if 0
6868 /*-----------------------------------------------------------------*/
6869 /* gencjne - compare and jump if not equal                         */
6870 /*-----------------------------------------------------------------*/
6871 static void gencjne(operand *left, operand *right, iCode *ifx)
6872 {
6873     symbol *tlbl  = newiTempLabel(NULL);
6874
6875     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6876     gencjneshort(left, right, lbl);
6877
6878     pic16_emitcode("mov","a,%s",one);
6879     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6880     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6881     pic16_emitcode("clr","a");
6882     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6883
6884     pic16_emitpLabel(lbl->key);
6885     pic16_emitpLabel(tlbl->key);
6886
6887 }
6888 #endif
6889
6890
6891 /*-----------------------------------------------------------------*/
6892 /* is_LitOp - check if operand has to be treated as literal        */
6893 /*-----------------------------------------------------------------*/
6894 static bool is_LitOp(operand *op)
6895 {
6896   return ((AOP_TYPE(op) == AOP_LIT)
6897       || ( (AOP_TYPE(op) == AOP_PCODE)
6898           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6899               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6900 }
6901
6902 /*-----------------------------------------------------------------*/
6903 /* is_LitAOp - check if operand has to be treated as literal        */
6904 /*-----------------------------------------------------------------*/
6905 static bool is_LitAOp(asmop *aop)
6906 {
6907   return ((aop->type == AOP_LIT)
6908       || ( (aop->type == AOP_PCODE)
6909           && ( (aop->aopu.pcop->type == PO_LITERAL)
6910               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6911 }
6912
6913
6914
6915 /*-----------------------------------------------------------------*/
6916 /* genCmpEq - generates code for equal to                          */
6917 /*-----------------------------------------------------------------*/
6918 static void genCmpEq (iCode *ic, iCode *ifx)
6919 {
6920   operand *left, *right, *result;
6921   symbol *falselbl = newiTempLabel(NULL);
6922   symbol *donelbl = newiTempLabel(NULL);
6923
6924   int preserve_result = 0;
6925   int generate_result = 0;
6926   int i=0;
6927   unsigned long lit = -1;
6928
6929   FENTRY;
6930   
6931   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6932   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6933   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6934  
6935   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6936
6937   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6938     {
6939       werror(W_POSSBUG2, __FILE__, __LINE__);
6940       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6941       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6942       goto release;
6943     }
6944
6945   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6946     {
6947       operand *tmp = right ;
6948       right = left;
6949       left = tmp;
6950     }
6951
6952   if (AOP_TYPE(right) == AOP_LIT) {
6953     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6954   }
6955
6956   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6957     preserve_result = 1;
6958
6959   if(result && AOP_SIZE(result))
6960     generate_result = 1;
6961
6962   if(generate_result && !preserve_result)
6963     {
6964       for(i = 0; i < AOP_SIZE(result); i++)
6965         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6966     }
6967
6968   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6969   for(i=0; i < AOP_SIZE(left); i++)
6970     {
6971       if(AOP_TYPE(left) != AOP_ACC)
6972         {
6973           if(is_LitOp(left))
6974             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6975           else
6976             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6977         }
6978       if(is_LitOp(right)) {
6979         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6980           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6981         }
6982       } else
6983         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6984
6985       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6986     }
6987
6988   // result == true
6989
6990   if(generate_result && preserve_result)
6991     {
6992       for(i = 0; i < AOP_SIZE(result); i++)
6993         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6994     }
6995
6996   if(generate_result)
6997     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6998
6999   if(generate_result && preserve_result)
7000     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7001
7002   if(ifx && IC_TRUE(ifx))
7003     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7004
7005   if(ifx && IC_FALSE(ifx))
7006     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7007
7008   pic16_emitpLabel(falselbl->key);
7009
7010   // result == false
7011
7012   if(ifx && IC_FALSE(ifx))
7013     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7014
7015   if(generate_result && preserve_result)
7016     {
7017       for(i = 0; i < AOP_SIZE(result); i++)
7018         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7019     }
7020
7021   pic16_emitpLabel(donelbl->key);
7022
7023   if(ifx)
7024     ifx->generated = 1;
7025
7026 release:
7027   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7028   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7029   pic16_freeAsmop(result,NULL,ic,TRUE);
7030
7031 }
7032
7033
7034 #if 0
7035 // old version kept for reference
7036
7037 /*-----------------------------------------------------------------*/
7038 /* genCmpEq - generates code for equal to                          */
7039 /*-----------------------------------------------------------------*/
7040 static void genCmpEq (iCode *ic, iCode *ifx)
7041 {
7042     operand *left, *right, *result;
7043     unsigned long lit = 0L;
7044     int size,offset=0;
7045     symbol *falselbl  = newiTempLabel(NULL);
7046
7047
7048     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7049
7050     if(ifx)
7051       DEBUGpic16_emitcode ("; ifx is non-null","");
7052     else
7053       DEBUGpic16_emitcode ("; ifx is null","");
7054
7055     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7056     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7057     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7058
7059     size = max(AOP_SIZE(left),AOP_SIZE(right));
7060
7061     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7062
7063     /* if literal, literal on the right or 
7064     if the right is in a pointer register and left 
7065     is not */
7066     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7067         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7068       operand *tmp = right ;
7069       right = left;
7070       left = tmp;
7071     }
7072
7073
7074     if(ifx && !AOP_SIZE(result)){
7075         symbol *tlbl;
7076         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7077         /* if they are both bit variables */
7078         if (AOP_TYPE(left) == AOP_CRY &&
7079             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7080                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7081             if(AOP_TYPE(right) == AOP_LIT){
7082                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7083                 if(lit == 0L){
7084                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7085                     pic16_emitcode("cpl","c");
7086                 } else if(lit == 1L) {
7087                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7088                 } else {
7089                     pic16_emitcode("clr","c");
7090                 }
7091                 /* AOP_TYPE(right) == AOP_CRY */
7092             } else {
7093                 symbol *lbl = newiTempLabel(NULL);
7094                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7095                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7096                 pic16_emitcode("cpl","c");
7097                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7098             }
7099             /* if true label then we jump if condition
7100             supplied is true */
7101             tlbl = newiTempLabel(NULL);
7102             if ( IC_TRUE(ifx) ) {
7103                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7104                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7105             } else {
7106                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7107                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7108             }
7109             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7110
7111                 {
7112                 /* left and right are both bit variables, result is carry */
7113                         resolvedIfx rIfx;
7114               
7115                         resolveIfx(&rIfx,ifx);
7116
7117                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7118                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7119                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7120                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7121                         genSkipz2(&rIfx,0);
7122                 }
7123         } else {
7124
7125                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7126
7127                         /* They're not both bit variables. Is the right a literal? */
7128                         if(AOP_TYPE(right) == AOP_LIT) {
7129                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7130             
7131                         switch(size) {
7132
7133                                 case 1:
7134                                         switch(lit & 0xff) {
7135                                                 case 1:
7136                                                                 if ( IC_TRUE(ifx) ) {
7137                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7138                                                                         emitSKPNZ;
7139                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7140                                                                 } else {
7141                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7142                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7143                                                                 }
7144                                                                 break;
7145                                                 case 0xff:
7146                                                                 if ( IC_TRUE(ifx) ) {
7147                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7148                                                                         emitSKPNZ;
7149                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7150                                                                 } else {
7151                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7152                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7153                                                                 }
7154                                                                 break;
7155                                                 default:
7156                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7157                                                                 if(lit)
7158                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7159                                                                 genSkip(ifx,'z');
7160                                         } // switch lit
7161
7162
7163                                         /* end of size == 1 */
7164                                         break;
7165               
7166                                 case 2:
7167                                         genc16bit2lit(left,lit,offset);
7168                                         genSkip(ifx,'z');
7169                                         break;
7170                                         /* end of size == 2 */
7171
7172                                 default:
7173                                         /* size is 4 */
7174                                         if(lit==0) {
7175                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7176                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7177                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7178                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7179                                                 genSkip(ifx,'z');
7180                                         } else {
7181                                                 /* search for patterns that can be optimized */
7182
7183                                                 genc16bit2lit(left,lit,0);
7184                                                 lit >>= 16;
7185                                                 if(lit) {
7186                                                                 if(IC_TRUE(ifx))
7187                                                                 emitSKPZ; // if hi word unequal
7188                                                                 else
7189                                                                 emitSKPNZ; // if hi word equal
7190                                                                 // fail early
7191                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7192                                                         genc16bit2lit(left,lit,2);
7193                                                         genSkip(ifx,'z');
7194                                                 } else {
7195                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7196                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7197                                                         genSkip(ifx,'z');
7198                                                 }
7199                                         }
7200                                                 pic16_emitpLabel(falselbl->key);
7201                                                 break;
7202
7203                         } // switch size
7204           
7205                         ifx->generated = 1;
7206                         goto release ;
7207             
7208
7209           } else if(AOP_TYPE(right) == AOP_CRY ) {
7210             /* we know the left is not a bit, but that the right is */
7211             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7212             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7213                       pic16_popGet(AOP(right),offset));
7214             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7215
7216             /* if the two are equal, then W will be 0 and the Z bit is set
7217              * we could test Z now, or go ahead and check the high order bytes if
7218              * the variable we're comparing is larger than a byte. */
7219
7220             while(--size)
7221               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7222
7223             if ( IC_TRUE(ifx) ) {
7224               emitSKPNZ;
7225               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7226               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7227             } else {
7228               emitSKPZ;
7229               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7230               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7231             }
7232
7233           } else {
7234             /* They're both variables that are larger than bits */
7235             int s = size;
7236
7237             tlbl = newiTempLabel(NULL);
7238
7239             while(size--) {
7240               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7241               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7242
7243               if ( IC_TRUE(ifx) ) {
7244                 if(size) {
7245                   emitSKPZ;
7246                 
7247                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7248
7249                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7250                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7251                 } else {
7252                   emitSKPNZ;
7253
7254                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7255
7256
7257                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7258                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7259                 }
7260               } else {
7261                 emitSKPZ;
7262
7263                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7264
7265                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7266                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7267               }
7268               offset++;
7269             }
7270             if(s>1 && IC_TRUE(ifx)) {
7271               pic16_emitpLabel(tlbl->key);
7272               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7273             }
7274           }
7275         }
7276         /* mark the icode as generated */
7277         ifx->generated = 1;
7278         goto release ;
7279     }
7280
7281     /* if they are both bit variables */
7282     if (AOP_TYPE(left) == AOP_CRY &&
7283         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7284         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7285         if(AOP_TYPE(right) == AOP_LIT){
7286             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7287             if(lit == 0L){
7288                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7289                 pic16_emitcode("cpl","c");
7290             } else if(lit == 1L) {
7291                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7292             } else {
7293                 pic16_emitcode("clr","c");
7294             }
7295             /* AOP_TYPE(right) == AOP_CRY */
7296         } else {
7297             symbol *lbl = newiTempLabel(NULL);
7298             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7299             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7300             pic16_emitcode("cpl","c");
7301             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7302         }
7303         /* c = 1 if egal */
7304         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7305             pic16_outBitC(result);
7306             goto release ;
7307         }
7308         if (ifx) {
7309             genIfxJump (ifx,"c");
7310             goto release ;
7311         }
7312         /* if the result is used in an arithmetic operation
7313         then put the result in place */
7314         pic16_outBitC(result);
7315     } else {
7316       
7317       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7318       gencjne(left,right,result,ifx);
7319 /*
7320       if(ifx) 
7321         gencjne(left,right,newiTempLabel(NULL));
7322       else {
7323         if(IC_TRUE(ifx)->key)
7324           gencjne(left,right,IC_TRUE(ifx)->key);
7325         else
7326           gencjne(left,right,IC_FALSE(ifx)->key);
7327         ifx->generated = 1;
7328         goto release ;
7329       }
7330       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7331         pic16_aopPut(AOP(result),"a",0);
7332         goto release ;
7333       }
7334
7335       if (ifx) {
7336         genIfxJump (ifx,"a");
7337         goto release ;
7338       }
7339 */
7340       /* if the result is used in an arithmetic operation
7341          then put the result in place */
7342 /*
7343       if (AOP_TYPE(result) != AOP_CRY) 
7344         pic16_outAcc(result);
7345 */
7346       /* leave the result in acc */
7347     }
7348
7349 release:
7350     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7351     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7352     pic16_freeAsmop(result,NULL,ic,TRUE);
7353 }
7354 #endif
7355
7356 /*-----------------------------------------------------------------*/
7357 /* ifxForOp - returns the icode containing the ifx for operand     */
7358 /*-----------------------------------------------------------------*/
7359 static iCode *ifxForOp ( operand *op, iCode *ic )
7360 {
7361   FENTRY2;
7362
7363     /* if true symbol then needs to be assigned */
7364     if (IS_TRUE_SYMOP(op))
7365         return NULL ;
7366
7367     /* if this has register type condition and
7368     the next instruction is ifx with the same operand
7369     and live to of the operand is upto the ifx only then */
7370     if (ic->next
7371         && ic->next->op == IFX
7372         && IC_COND(ic->next)->key == op->key
7373         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7374         ) {
7375                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7376           return ic->next;
7377     }
7378
7379     /*
7380     if (ic->next &&
7381         ic->next->op == IFX &&
7382         IC_COND(ic->next)->key == op->key) {
7383       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7384       return ic->next;
7385     }
7386     */
7387
7388     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7389     if (ic->next &&
7390         ic->next->op == IFX)
7391       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7392
7393     if (ic->next &&
7394         ic->next->op == IFX &&
7395         IC_COND(ic->next)->key == op->key) {
7396       DEBUGpic16_emitcode ("; "," key is okay");
7397       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7398                            OP_SYMBOL(op)->liveTo,
7399                            ic->next->seq);
7400     }
7401
7402 #if 0
7403     /* the code below is completely untested
7404      * it just allows ulong2fs.c compile -- VR */
7405          
7406     ic = ic->next;
7407     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7408                                         __FILE__, __FUNCTION__, __LINE__);
7409         
7410     /* if this has register type condition and
7411     the next instruction is ifx with the same operand
7412     and live to of the operand is upto the ifx only then */
7413     if (ic->next &&
7414         ic->next->op == IFX &&
7415         IC_COND(ic->next)->key == op->key &&
7416         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7417         return ic->next;
7418
7419     if (ic->next &&
7420         ic->next->op == IFX &&
7421         IC_COND(ic->next)->key == op->key) {
7422       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7423       return ic->next;
7424     }
7425
7426     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7427                                         __FILE__, __FUNCTION__, __LINE__);
7428
7429 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7430 #endif
7431
7432     return NULL;
7433 }
7434 /*-----------------------------------------------------------------*/
7435 /* genAndOp - for && operation                                     */
7436 /*-----------------------------------------------------------------*/
7437 static void genAndOp (iCode *ic)
7438 {
7439   operand *left,*right, *result;
7440 /*     symbol *tlbl; */
7441
7442     FENTRY;
7443
7444     /* note here that && operations that are in an
7445     if statement are taken away by backPatchLabels
7446     only those used in arthmetic operations remain */
7447     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7448     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7449     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7450
7451     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7452
7453     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7454     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7455     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7456
7457     /* if both are bit variables */
7458 /*     if (AOP_TYPE(left) == AOP_CRY && */
7459 /*         AOP_TYPE(right) == AOP_CRY ) { */
7460 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7461 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7462 /*         pic16_outBitC(result); */
7463 /*     } else { */
7464 /*         tlbl = newiTempLabel(NULL); */
7465 /*         pic16_toBoolean(left);     */
7466 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7467 /*         pic16_toBoolean(right); */
7468 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7469 /*         pic16_outBitAcc(result); */
7470 /*     } */
7471
7472     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7473     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7474     pic16_freeAsmop(result,NULL,ic,TRUE);
7475 }
7476
7477
7478 /*-----------------------------------------------------------------*/
7479 /* genOrOp - for || operation                                      */
7480 /*-----------------------------------------------------------------*/
7481 /*
7482   tsd pic port -
7483   modified this code, but it doesn't appear to ever get called
7484 */
7485
7486 static void genOrOp (iCode *ic)
7487 {
7488   operand *left,*right, *result;
7489   symbol *tlbl;
7490
7491     FENTRY;  
7492
7493   /* note here that || operations that are in an
7494     if statement are taken away by backPatchLabels
7495     only those used in arthmetic operations remain */
7496     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7497     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7498     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7499
7500     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7501
7502     /* if both are bit variables */
7503     if (AOP_TYPE(left) == AOP_CRY &&
7504         AOP_TYPE(right) == AOP_CRY ) {
7505       pic16_emitcode("clrc","");
7506       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7507                AOP(left)->aopu.aop_dir,
7508                AOP(left)->aopu.aop_dir);
7509       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7510                AOP(right)->aopu.aop_dir,
7511                AOP(right)->aopu.aop_dir);
7512       pic16_emitcode("setc","");
7513
7514     } else {
7515         tlbl = newiTempLabel(NULL);
7516         pic16_toBoolean(left);
7517         emitSKPZ;
7518         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7519         pic16_toBoolean(right);
7520         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7521
7522         pic16_outBitAcc(result);
7523     }
7524
7525     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7526     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7527     pic16_freeAsmop(result,NULL,ic,TRUE);            
7528 }
7529
7530 /*-----------------------------------------------------------------*/
7531 /* isLiteralBit - test if lit == 2^n                               */
7532 /*-----------------------------------------------------------------*/
7533 static int isLiteralBit(unsigned long lit)
7534 {
7535     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7536     0x100L,0x200L,0x400L,0x800L,
7537     0x1000L,0x2000L,0x4000L,0x8000L,
7538     0x10000L,0x20000L,0x40000L,0x80000L,
7539     0x100000L,0x200000L,0x400000L,0x800000L,
7540     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7541     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7542     int idx;
7543     
7544     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7545     for(idx = 0; idx < 32; idx++)
7546         if(lit == pw[idx])
7547             return idx+1;
7548     return 0;
7549 }
7550
7551 /*-----------------------------------------------------------------*/
7552 /* continueIfTrue -                                                */
7553 /*-----------------------------------------------------------------*/
7554 static void continueIfTrue (iCode *ic)
7555 {
7556   FENTRY;
7557   if(IC_TRUE(ic))
7558     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7559   ic->generated = 1;
7560 }
7561
7562 /*-----------------------------------------------------------------*/
7563 /* jmpIfTrue -                                                     */
7564 /*-----------------------------------------------------------------*/
7565 static void jumpIfTrue (iCode *ic)
7566 {
7567   FENTRY;
7568   if(!IC_TRUE(ic))
7569     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7570   ic->generated = 1;
7571 }
7572
7573 /*-----------------------------------------------------------------*/
7574 /* jmpTrueOrFalse -                                                */
7575 /*-----------------------------------------------------------------*/
7576 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7577 {
7578   // ugly but optimized by peephole
7579   FENTRY;
7580   if(IC_TRUE(ic)){
7581     symbol *nlbl = newiTempLabel(NULL);
7582       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7583       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7584       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7585       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7586   } else {
7587     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7588     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7589   }
7590   ic->generated = 1;
7591 }
7592
7593 /*-----------------------------------------------------------------*/
7594 /* genAnd  - code for and                                          */
7595 /*-----------------------------------------------------------------*/
7596 static void genAnd (iCode *ic, iCode *ifx)
7597 {
7598   operand *left, *right, *result;
7599   int size, offset=0;  
7600   unsigned long lit = 0L;
7601   int bytelit = 0;
7602   resolvedIfx rIfx;
7603
7604     FENTRY;
7605     
7606   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7607   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7608   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7609
7610   resolveIfx(&rIfx,ifx);
7611
7612   /* if left is a literal & right is not then exchange them */
7613   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7614       AOP_NEEDSACC(left)) {
7615     operand *tmp = right ;
7616     right = left;
7617     left = tmp;
7618   }
7619
7620   /* if result = right then exchange them */
7621   if(pic16_sameRegs(AOP(result),AOP(right))){
7622     operand *tmp = right ;
7623     right = left;
7624     left = tmp;
7625   }
7626
7627   /* if right is bit then exchange them */
7628   if (AOP_TYPE(right) == AOP_CRY &&
7629       AOP_TYPE(left) != AOP_CRY){
7630     operand *tmp = right ;
7631     right = left;
7632     left = tmp;
7633   }
7634   if(AOP_TYPE(right) == AOP_LIT)
7635     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7636
7637   size = AOP_SIZE(result);
7638
7639   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7640
7641   // if(bit & yy)
7642   // result = bit & yy;
7643   if (AOP_TYPE(left) == AOP_CRY){
7644     // c = bit & literal;
7645     if(AOP_TYPE(right) == AOP_LIT){
7646       if(lit & 1) {
7647         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7648           // no change
7649           goto release;
7650         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7651       } else {
7652         // bit(result) = 0;
7653         if(size && (AOP_TYPE(result) == AOP_CRY)){
7654           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7655           goto release;
7656         }
7657         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7658           jumpIfTrue(ifx);
7659           goto release;
7660         }
7661         pic16_emitcode("clr","c");
7662       }
7663     } else {
7664       if (AOP_TYPE(right) == AOP_CRY){
7665         // c = bit & bit;
7666         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7667         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7668       } else {
7669         // c = bit & val;
7670         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7671         // c = lsb
7672         pic16_emitcode("rrc","a");
7673         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7674       }
7675     }
7676     // bit = c
7677     // val = c
7678     if(size)
7679       pic16_outBitC(result);
7680     // if(bit & ...)
7681     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7682       genIfxJump(ifx, "c");           
7683     goto release ;
7684   }
7685
7686   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7687   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7688   if((AOP_TYPE(right) == AOP_LIT) &&
7689      (AOP_TYPE(result) == AOP_CRY) &&
7690      (AOP_TYPE(left) != AOP_CRY)){
7691     int posbit = isLiteralBit(lit);
7692     /* left &  2^n */
7693     if(posbit){
7694       posbit--;
7695       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7696       // bit = left & 2^n
7697       if(size)
7698         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7699       // if(left &  2^n)
7700       else{
7701         if(ifx){
7702 /*
7703           if(IC_TRUE(ifx)) {
7704             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7705             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7706           } else {
7707             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7708             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7709           }
7710 */
7711         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7712         size = AOP_SIZE(left);
7713
7714         {
7715           int bp = posbit, ofs=0;
7716           
7717             while(bp > 7) {
7718               bp -= 8;
7719               ofs++;
7720             }
7721
7722           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7723                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7724
7725         }
7726 /*
7727           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7728                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7729 */
7730           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7731           
7732           ifx->generated = 1;
7733         }
7734         goto release;
7735       }
7736     } else {
7737       symbol *tlbl = newiTempLabel(NULL);
7738       int sizel = AOP_SIZE(left);
7739
7740       if(size)
7741         emitSETC;
7742
7743       while(sizel--) {
7744         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7745
7746           /* patch provided by Aaron Colwell */
7747           if((posbit = isLiteralBit(bytelit)) != 0) {
7748               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7749                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7750                                                 (posbit-1),0, PO_GPR_REGISTER));
7751
7752               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7753 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7754           } else {
7755               if (bytelit == 0xff) {
7756                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7757                    * a peephole could optimize it out -- VR */
7758                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7759               } else {
7760                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7761                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7762               }
7763
7764               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7765                             pic16_popGetLabel(tlbl->key));
7766           }
7767         
7768 #if 0
7769           /* old code, left here for reference -- VR 09/2004 */
7770           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7771           // byte ==  2^n ?
7772           if((posbit = isLiteralBit(bytelit)) != 0)
7773             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7774           else{
7775             if(bytelit != 0x0FFL)
7776               pic16_emitcode("anl","a,%s",
7777                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7778             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7779           }
7780 #endif
7781         }
7782         offset++;
7783       }
7784       // bit = left & literal
7785       if(size) {
7786         emitCLRC;
7787         pic16_emitpLabel(tlbl->key);
7788       }
7789       // if(left & literal)
7790       else {
7791         if(ifx) {
7792           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7793           ifx->generated = 1;
7794         }
7795         pic16_emitpLabel(tlbl->key);
7796         goto release;
7797       }
7798     }
7799
7800     pic16_outBitC(result);
7801     goto release ;
7802   }
7803
7804   /* if left is same as result */
7805   if(pic16_sameRegs(AOP(result),AOP(left))){
7806     int know_W = -1;
7807     for(;size--; offset++,lit>>=8) {
7808       if(AOP_TYPE(right) == AOP_LIT){
7809         switch(lit & 0xff) {
7810         case 0x00:
7811           /*  and'ing with 0 has clears the result */
7812 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7813           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7814           break;
7815         case 0xff:
7816           /* and'ing with 0xff is a nop when the result and left are the same */
7817           break;
7818
7819         default:
7820           {
7821             int p = pic16_my_powof2( (~lit) & 0xff );
7822             if(p>=0) {
7823               /* only one bit is set in the literal, so use a bcf instruction */
7824 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7825               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7826
7827             } else {
7828               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7829               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7830               if(know_W != (lit&0xff))
7831                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7832               know_W = lit &0xff;
7833               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7834             }
7835           }    
7836         }
7837       } else {
7838         if (AOP_TYPE(left) == AOP_ACC) {
7839           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7840         } else {                    
7841           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7842           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7843
7844         }
7845       }
7846     }
7847
7848   } else {
7849     // left & result in different registers
7850     if(AOP_TYPE(result) == AOP_CRY){
7851       // result = bit
7852       // if(size), result in bit
7853       // if(!size && ifx), conditional oper: if(left & right)
7854       symbol *tlbl = newiTempLabel(NULL);
7855       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7856       if(size)
7857         pic16_emitcode("setb","c");
7858       while(sizer--){
7859         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7860         pic16_emitcode("anl","a,%s",
7861                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7862         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7863         offset++;
7864       }
7865       if(size){
7866         CLRC;
7867         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7868         pic16_outBitC(result);
7869       } else if(ifx)
7870         jmpTrueOrFalse(ifx, tlbl);
7871     } else {
7872       for(;(size--);offset++) {
7873         // normal case
7874         // result = left & right
7875         if(AOP_TYPE(right) == AOP_LIT){
7876           int t = (lit >> (offset*8)) & 0x0FFL;
7877           switch(t) { 
7878           case 0x00:
7879             pic16_emitcode("clrf","%s",
7880                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7881             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7882             break;
7883           case 0xff:
7884             pic16_emitcode("movf","%s,w",
7885                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7886             pic16_emitcode("movwf","%s",
7887                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7888             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7889             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7890             break;
7891           default:
7892             pic16_emitcode("movlw","0x%x",t);
7893             pic16_emitcode("andwf","%s,w",
7894                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7895             pic16_emitcode("movwf","%s",
7896                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7897               
7898             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7899             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7900             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7901           }
7902           continue;
7903         }
7904
7905         if (AOP_TYPE(left) == AOP_ACC) {
7906           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7907           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7908         } else {
7909           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7910           pic16_emitcode("andwf","%s,w",
7911                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7912           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7913           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7914         }
7915         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7916         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7917       }
7918     }
7919   }
7920
7921   release :
7922     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7923   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7924   pic16_freeAsmop(result,NULL,ic,TRUE);     
7925 }
7926
7927 /*-----------------------------------------------------------------*/
7928 /* genOr  - code for or                                            */
7929 /*-----------------------------------------------------------------*/
7930 static void genOr (iCode *ic, iCode *ifx)
7931 {
7932     operand *left, *right, *result;
7933     int size, offset=0;
7934     unsigned long lit = 0L;
7935
7936     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7937     FENTRY;
7938
7939     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7940     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7941     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7942
7943     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7944
7945     /* if left is a literal & right is not then exchange them */
7946     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7947         AOP_NEEDSACC(left)) {
7948         operand *tmp = right ;
7949         right = left;
7950         left = tmp;
7951     }
7952
7953     /* if result = right then exchange them */
7954     if(pic16_sameRegs(AOP(result),AOP(right))){
7955         operand *tmp = right ;
7956         right = left;
7957         left = tmp;
7958     }
7959
7960     /* if right is bit then exchange them */
7961     if (AOP_TYPE(right) == AOP_CRY &&
7962         AOP_TYPE(left) != AOP_CRY){
7963         operand *tmp = right ;
7964         right = left;
7965         left = tmp;
7966     }
7967
7968     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7969
7970     if(AOP_TYPE(right) == AOP_LIT)
7971         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7972
7973     size = AOP_SIZE(result);
7974
7975     // if(bit | yy)
7976     // xx = bit | yy;
7977     if (AOP_TYPE(left) == AOP_CRY){
7978         if(AOP_TYPE(right) == AOP_LIT){
7979             // c = bit & literal;
7980             if(lit){
7981                 // lit != 0 => result = 1
7982                 if(AOP_TYPE(result) == AOP_CRY){
7983                   if(size)
7984                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7985                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7986                   //     AOP(result)->aopu.aop_dir,
7987                   //     AOP(result)->aopu.aop_dir);
7988                     else if(ifx)
7989                         continueIfTrue(ifx);
7990                     goto release;
7991                 }
7992             } else {
7993                 // lit == 0 => result = left
7994                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7995                     goto release;
7996                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7997             }
7998         } else {
7999             if (AOP_TYPE(right) == AOP_CRY){
8000               if(pic16_sameRegs(AOP(result),AOP(left))){
8001                 // c = bit | bit;
8002                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8003                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8004                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8005
8006                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8007                          AOP(result)->aopu.aop_dir,
8008                          AOP(result)->aopu.aop_dir);
8009                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8010                          AOP(right)->aopu.aop_dir,
8011                          AOP(right)->aopu.aop_dir);
8012                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8013                          AOP(result)->aopu.aop_dir,
8014                          AOP(result)->aopu.aop_dir);
8015               } else {
8016                 if( AOP_TYPE(result) == AOP_ACC) {
8017                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8018                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8019                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8020                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8021
8022                 } else {
8023
8024                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8025                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8026                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8027                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8028
8029                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8030                                  AOP(result)->aopu.aop_dir,
8031                                  AOP(result)->aopu.aop_dir);
8032                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8033                                  AOP(right)->aopu.aop_dir,
8034                                  AOP(right)->aopu.aop_dir);
8035                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8036                                  AOP(left)->aopu.aop_dir,
8037                                  AOP(left)->aopu.aop_dir);
8038                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8039                                  AOP(result)->aopu.aop_dir,
8040                                  AOP(result)->aopu.aop_dir);
8041                 }
8042               }
8043             } else {
8044                 // c = bit | val;
8045                 symbol *tlbl = newiTempLabel(NULL);
8046                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8047
8048
8049                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8050                 if( AOP_TYPE(right) == AOP_ACC) {
8051                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8052                   emitSKPNZ;
8053                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8054                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8055                 }
8056
8057
8058
8059                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8060                     pic16_emitcode(";XXX setb","c");
8061                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8062                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8063                 pic16_toBoolean(right);
8064                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8065                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8066                     jmpTrueOrFalse(ifx, tlbl);
8067                     goto release;
8068                 } else {
8069                     CLRC;
8070                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8071                 }
8072             }
8073         }
8074         // bit = c
8075         // val = c
8076         if(size)
8077             pic16_outBitC(result);
8078         // if(bit | ...)
8079         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8080             genIfxJump(ifx, "c");           
8081         goto release ;
8082     }
8083
8084     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8085     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8086     if((AOP_TYPE(right) == AOP_LIT) &&
8087        (AOP_TYPE(result) == AOP_CRY) &&
8088        (AOP_TYPE(left) != AOP_CRY)){
8089         if(lit){
8090           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8091             // result = 1
8092             if(size)
8093                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8094             else 
8095                 continueIfTrue(ifx);
8096             goto release;
8097         } else {
8098           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8099             // lit = 0, result = boolean(left)
8100             if(size)
8101                 pic16_emitcode(";XXX setb","c");
8102             pic16_toBoolean(right);
8103             if(size){
8104                 symbol *tlbl = newiTempLabel(NULL);
8105                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8106                 CLRC;
8107                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8108             } else {
8109                 genIfxJump (ifx,"a");
8110                 goto release;
8111             }
8112         }
8113         pic16_outBitC(result);
8114         goto release ;
8115     }
8116
8117     /* if left is same as result */
8118     if(pic16_sameRegs(AOP(result),AOP(left))){
8119       int know_W = -1;
8120       for(;size--; offset++,lit>>=8) {
8121         if(AOP_TYPE(right) == AOP_LIT){
8122           if((lit & 0xff) == 0)
8123             /*  or'ing with 0 has no effect */
8124             continue;
8125           else {
8126             int p = pic16_my_powof2(lit & 0xff);
8127             if(p>=0) {
8128               /* only one bit is set in the literal, so use a bsf instruction */
8129               pic16_emitpcode(POC_BSF,
8130                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8131             } else {
8132               if(know_W != (lit & 0xff))
8133                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8134               know_W = lit & 0xff;
8135               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8136             }
8137                     
8138           }
8139         } else {
8140           if (AOP_TYPE(left) == AOP_ACC) {
8141             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8142 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8143           } else {                  
8144             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8145             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8146
8147 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8148 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8149
8150           }
8151         }
8152       }
8153     } else {
8154         // left & result in different registers
8155         if(AOP_TYPE(result) == AOP_CRY){
8156             // result = bit
8157             // if(size), result in bit
8158             // if(!size && ifx), conditional oper: if(left | right)
8159             symbol *tlbl = newiTempLabel(NULL);
8160             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8161             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8162
8163
8164             if(size)
8165                 pic16_emitcode(";XXX setb","c");
8166             while(sizer--){
8167                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8168                 pic16_emitcode(";XXX orl","a,%s",
8169                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8170                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8171                 offset++;
8172             }
8173             if(size){
8174                 CLRC;
8175                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8176                 pic16_outBitC(result);
8177             } else if(ifx)
8178                 jmpTrueOrFalse(ifx, tlbl);
8179         } else for(;(size--);offset++){
8180           // normal case
8181           // result = left & right
8182           if(AOP_TYPE(right) == AOP_LIT){
8183             int t = (lit >> (offset*8)) & 0x0FFL;
8184             switch(t) { 
8185             case 0x00:
8186               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8187               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8188
8189 //            pic16_emitcode("movf","%s,w",
8190 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191 //            pic16_emitcode("movwf","%s",
8192 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8193               break;
8194             default:
8195               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8196               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8197               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8198
8199 //            pic16_emitcode("movlw","0x%x",t);
8200 //            pic16_emitcode("iorwf","%s,w",
8201 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8202 //            pic16_emitcode("movwf","%s",
8203 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8204               
8205             }
8206             continue;
8207           }
8208
8209           // faster than result <- left, anl result,right
8210           // and better if result is SFR
8211           if (AOP_TYPE(left) == AOP_ACC) {
8212             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8213 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8214           } else {
8215             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8216             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8217
8218 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8219 //          pic16_emitcode("iorwf","%s,w",
8220 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8221           }
8222           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8223 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8224         }
8225     }
8226
8227 release :
8228     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8229     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8230     pic16_freeAsmop(result,NULL,ic,TRUE);     
8231 }
8232
8233 /*-----------------------------------------------------------------*/
8234 /* genXor - code for xclusive or                                   */
8235 /*-----------------------------------------------------------------*/
8236 static void genXor (iCode *ic, iCode *ifx)
8237 {
8238   operand *left, *right, *result;
8239   int size, offset=0;
8240   unsigned long lit = 0L;
8241
8242   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8243   FENTRY;
8244
8245   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8246   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8247   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8248
8249   /* if left is a literal & right is not ||
8250      if left needs acc & right does not */
8251   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8252       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8253     operand *tmp = right ;
8254     right = left;
8255     left = tmp;
8256   }
8257
8258   /* if result = right then exchange them */
8259   if(pic16_sameRegs(AOP(result),AOP(right))){
8260     operand *tmp = right ;
8261     right = left;
8262     left = tmp;
8263   }
8264
8265   /* if right is bit then exchange them */
8266   if (AOP_TYPE(right) == AOP_CRY &&
8267       AOP_TYPE(left) != AOP_CRY){
8268     operand *tmp = right ;
8269     right = left;
8270     left = tmp;
8271   }
8272   if(AOP_TYPE(right) == AOP_LIT)
8273     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8274
8275   size = AOP_SIZE(result);
8276
8277   // if(bit ^ yy)
8278   // xx = bit ^ yy;
8279   if (AOP_TYPE(left) == AOP_CRY){
8280     if(AOP_TYPE(right) == AOP_LIT){
8281       // c = bit & literal;
8282       if(lit>>1){
8283         // lit>>1  != 0 => result = 1
8284         if(AOP_TYPE(result) == AOP_CRY){
8285           if(size)
8286             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8287             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8288           else if(ifx)
8289             continueIfTrue(ifx);
8290           goto release;
8291         }
8292         pic16_emitcode("setb","c");
8293       } else{
8294         // lit == (0 or 1)
8295         if(lit == 0){
8296           // lit == 0, result = left
8297           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8298             goto release;
8299           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8300         } else{
8301           // lit == 1, result = not(left)
8302           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8303             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8304             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8305             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8306             goto release;
8307           } else {
8308             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8309             pic16_emitcode("cpl","c");
8310           }
8311         }
8312       }
8313
8314     } else {
8315       // right != literal
8316       symbol *tlbl = newiTempLabel(NULL);
8317       if (AOP_TYPE(right) == AOP_CRY){
8318         // c = bit ^ bit;
8319         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8320       }
8321       else{
8322         int sizer = AOP_SIZE(right);
8323         // c = bit ^ val
8324         // if val>>1 != 0, result = 1
8325         pic16_emitcode("setb","c");
8326         while(sizer){
8327           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8328           if(sizer == 1)
8329             // test the msb of the lsb
8330             pic16_emitcode("anl","a,#0xfe");
8331           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8332           sizer--;
8333         }
8334         // val = (0,1)
8335         pic16_emitcode("rrc","a");
8336       }
8337       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8338       pic16_emitcode("cpl","c");
8339       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8340     }
8341     // bit = c
8342     // val = c
8343     if(size)
8344       pic16_outBitC(result);
8345     // if(bit | ...)
8346     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8347       genIfxJump(ifx, "c");           
8348     goto release ;
8349   }
8350
8351   if(pic16_sameRegs(AOP(result),AOP(left))){
8352     /* if left is same as result */
8353     for(;size--; offset++) {
8354       if(AOP_TYPE(right) == AOP_LIT){
8355         int t  = (lit >> (offset*8)) & 0x0FFL;
8356         if(t == 0x00L)
8357           continue;
8358         else
8359           if (IS_AOP_PREG(left)) {
8360             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8361             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8362             pic16_aopPut(AOP(result),"a",offset);
8363           } else {
8364             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8365             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8366             pic16_emitcode("xrl","%s,%s",
8367                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8368                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8369           }
8370       } else {
8371         if (AOP_TYPE(left) == AOP_ACC)
8372           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8373         else {
8374           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8375           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8376 /*
8377           if (IS_AOP_PREG(left)) {
8378             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8379             pic16_aopPut(AOP(result),"a",offset);
8380           } else
8381             pic16_emitcode("xrl","%s,a",
8382                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8383 */
8384         }
8385       }
8386     }
8387   } else {
8388     // left & result in different registers
8389     if(AOP_TYPE(result) == AOP_CRY){
8390       // result = bit
8391       // if(size), result in bit
8392       // if(!size && ifx), conditional oper: if(left ^ right)
8393       symbol *tlbl = newiTempLabel(NULL);
8394       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8395       if(size)
8396         pic16_emitcode("setb","c");
8397       while(sizer--){
8398         if((AOP_TYPE(right) == AOP_LIT) &&
8399            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8400           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8401         } else {
8402           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8403           pic16_emitcode("xrl","a,%s",
8404                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8405         }
8406         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8407         offset++;
8408       }
8409       if(size){
8410         CLRC;
8411         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8412         pic16_outBitC(result);
8413       } else if(ifx)
8414         jmpTrueOrFalse(ifx, tlbl);
8415     } else for(;(size--);offset++){
8416       // normal case
8417       // result = left & right
8418       if(AOP_TYPE(right) == AOP_LIT){
8419         int t = (lit >> (offset*8)) & 0x0FFL;
8420         switch(t) { 
8421         case 0x00:
8422           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8423           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8424           pic16_emitcode("movf","%s,w",
8425                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8426           pic16_emitcode("movwf","%s",
8427                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8428           break;
8429         case 0xff:
8430           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8431           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8432           pic16_emitcode("comf","%s,w",
8433                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8434           pic16_emitcode("movwf","%s",
8435                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8436           break;
8437         default:
8438           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8439           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8440           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8441           pic16_emitcode("movlw","0x%x",t);
8442           pic16_emitcode("xorwf","%s,w",
8443                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8444           pic16_emitcode("movwf","%s",
8445                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8446
8447         }
8448         continue;
8449       }
8450
8451       // faster than result <- left, anl result,right
8452       // and better if result is SFR
8453       if (AOP_TYPE(left) == AOP_ACC) {
8454         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8455         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8456       } else {
8457         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8458         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8459         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8460         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8461       }
8462       if ( AOP_TYPE(result) != AOP_ACC){
8463         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8464         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8465       }
8466     }
8467   }
8468
8469   release :
8470     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8471   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8472   pic16_freeAsmop(result,NULL,ic,TRUE);     
8473 }
8474
8475 /*-----------------------------------------------------------------*/
8476 /* genInline - write the inline code out                           */
8477 /*-----------------------------------------------------------------*/
8478 static void genInline (iCode *ic)
8479 {
8480   char *buffer, *bp, *bp1;
8481     
8482         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8483
8484         _G.inLine += (!options.asmpeep);
8485
8486         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8487         strcpy(buffer,IC_INLINE(ic));
8488         
8489         while((bp1=strstr(bp, "\\n"))) {
8490           *bp1++ = '\n';
8491           *bp1++ = ' ';
8492           bp = bp1;
8493         }
8494         bp = bp1 = buffer;
8495
8496 #if 0
8497   /* This is an experimental code for #pragma inline
8498      and is temporarily disabled for 2.5.0 release */
8499         if(asmInlineMap)
8500         {
8501           symbol *sym;
8502           char *s;
8503           char *cbuf;
8504           int cblen;
8505
8506             cbuf = Safe_strdup(buffer);
8507             cblen = strlen(buffer)+1;
8508             memset(cbuf, 0, cblen);
8509
8510             bp = buffer;
8511             bp1 = cbuf;
8512             while(*bp) {
8513               if(*bp != '%')*bp1++ = *bp++;
8514               else {
8515                 int i;
8516
8517                   bp++;
8518                   i = *bp - '0';
8519                   if(i>elementsInSet(asmInlineMap))break;
8520                   
8521                   bp++;
8522                   s = indexSet(asmInlineMap, i);
8523                   DEBUGpc("searching symbol s = `%s'", s);
8524                   sym = findSym(SymbolTab, NULL, s);
8525
8526                   if(sym->reqv) {
8527                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8528                   } else {
8529                     strcat(bp1, sym->rname);
8530                   }
8531                   
8532                   while(*bp1)bp1++;
8533               }
8534               
8535               if(strlen(bp1) > cblen - 16) {
8536                 int i = strlen(cbuf);
8537                 cblen += 50;
8538                 cbuf = realloc(cbuf, cblen);
8539                 memset(cbuf+i, 0, 50);
8540                 bp1 = cbuf + i;
8541               }
8542             }
8543             
8544             free(buffer);
8545             buffer = Safe_strdup( cbuf );
8546             free(cbuf);
8547             
8548             bp = bp1 = buffer;
8549         }
8550 #endif  /* 0 */
8551
8552         /* emit each line as a code */
8553         while (*bp) {
8554                 if (*bp == '\n') {
8555                         *bp++ = '\0';
8556
8557                         if(*bp1)
8558                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8559                         bp1 = bp;
8560                 } else {
8561                         if (*bp == ':') {
8562                                 bp++;
8563                                 *bp = '\0';
8564                                 bp++;
8565
8566                                 /* print label, use this special format with NULL directive
8567                                  * to denote that the argument should not be indented with tab */
8568                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8569                                 bp1 = bp;
8570                         } if (*bp == ';') {
8571                                 /* advance to end of line (prevent splitting of comments at ':' */
8572                                 while (*bp && *bp != '\n') {
8573                                         bp++;
8574                                 } // while
8575                         } else
8576                                 bp++;
8577                 }
8578         }
8579
8580         if ((bp1 != bp) && *bp1)
8581                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8582
8583
8584     Safe_free(buffer);
8585
8586     _G.inLine -= (!options.asmpeep);
8587 }
8588
8589 /*-----------------------------------------------------------------*/
8590 /* genRRC - rotate right with carry                                */
8591 /*-----------------------------------------------------------------*/
8592 static void genRRC (iCode *ic)
8593 {
8594   operand *left , *result ;
8595   int size, offset = 0, same;
8596
8597   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8598
8599   /* rotate right with carry */
8600   left = IC_LEFT(ic);
8601   result=IC_RESULT(ic);
8602   pic16_aopOp (left,ic,FALSE);
8603   pic16_aopOp (result,ic,TRUE);
8604
8605   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8606
8607   same = pic16_sameRegs(AOP(result),AOP(left));
8608
8609   size = AOP_SIZE(result);    
8610
8611   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8612
8613   /* get the lsb and put it into the carry */
8614   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8615
8616   offset = 0 ;
8617
8618   while(size--) {
8619
8620     if(same) {
8621       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8622     } else {
8623       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8624       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8625     }
8626
8627     offset++;
8628   }
8629
8630   pic16_freeAsmop(left,NULL,ic,TRUE);
8631   pic16_freeAsmop(result,NULL,ic,TRUE);
8632 }
8633
8634 /*-----------------------------------------------------------------*/
8635 /* genRLC - generate code for rotate left with carry               */
8636 /*-----------------------------------------------------------------*/
8637 static void genRLC (iCode *ic)
8638 {    
8639   operand *left , *result ;
8640   int size, offset = 0;
8641   int same;
8642
8643   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8644   /* rotate right with carry */
8645   left = IC_LEFT(ic);
8646   result=IC_RESULT(ic);
8647   pic16_aopOp (left,ic,FALSE);
8648   pic16_aopOp (result,ic,TRUE);
8649
8650   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8651
8652   same = pic16_sameRegs(AOP(result),AOP(left));
8653
8654   /* move it to the result */
8655   size = AOP_SIZE(result);    
8656
8657   /* get the msb and put it into the carry */
8658   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8659
8660   offset = 0 ;
8661
8662   while(size--) {
8663
8664     if(same) {
8665       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8666     } else {
8667       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8668       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8669     }
8670
8671     offset++;
8672   }
8673
8674
8675   pic16_freeAsmop(left,NULL,ic,TRUE);
8676   pic16_freeAsmop(result,NULL,ic,TRUE);
8677 }
8678
8679
8680 /* gpasm can get the highest order bit with HIGH/UPPER
8681  * so the following probably is not needed -- VR */
8682  
8683 /*-----------------------------------------------------------------*/
8684 /* genGetHbit - generates code get highest order bit               */
8685 /*-----------------------------------------------------------------*/
8686 static void genGetHbit (iCode *ic)
8687 {
8688     operand *left, *result;
8689     left = IC_LEFT(ic);
8690     result=IC_RESULT(ic);
8691     pic16_aopOp (left,ic,FALSE);
8692     pic16_aopOp (result,ic,FALSE);
8693
8694     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8695     /* get the highest order byte into a */
8696     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8697     if(AOP_TYPE(result) == AOP_CRY){
8698         pic16_emitcode("rlc","a");
8699         pic16_outBitC(result);
8700     }
8701     else{
8702         pic16_emitcode("rl","a");
8703         pic16_emitcode("anl","a,#0x01");
8704         pic16_outAcc(result);
8705     }
8706
8707
8708     pic16_freeAsmop(left,NULL,ic,TRUE);
8709     pic16_freeAsmop(result,NULL,ic,TRUE);
8710 }
8711
8712 #if 0
8713 /*-----------------------------------------------------------------*/
8714 /* AccRol - rotate left accumulator by known count                 */
8715 /*-----------------------------------------------------------------*/
8716 static void AccRol (int shCount)
8717 {
8718     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8719     shCount &= 0x0007;              // shCount : 0..7
8720     switch(shCount){
8721         case 0 :
8722             break;
8723         case 1 :
8724             pic16_emitcode("rl","a");
8725             break;
8726         case 2 :
8727             pic16_emitcode("rl","a");
8728             pic16_emitcode("rl","a");
8729             break;
8730         case 3 :
8731             pic16_emitcode("swap","a");
8732             pic16_emitcode("rr","a");
8733             break;
8734         case 4 :
8735             pic16_emitcode("swap","a");
8736             break;
8737         case 5 :
8738             pic16_emitcode("swap","a");
8739             pic16_emitcode("rl","a");
8740             break;
8741         case 6 :
8742             pic16_emitcode("rr","a");
8743             pic16_emitcode("rr","a");
8744             break;
8745         case 7 :
8746             pic16_emitcode("rr","a");
8747             break;
8748     }
8749 }
8750 #endif
8751
8752 /*-----------------------------------------------------------------*/
8753 /* AccLsh - left shift accumulator by known count                  */
8754 /*-----------------------------------------------------------------*/
8755 static void AccLsh (int shCount, int doMask)
8756 {
8757         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8758         switch(shCount){
8759                 case 0 :
8760                         return;
8761                         break;
8762                 case 1 :
8763                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8764                         break;
8765                 case 2 :
8766                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8767                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8768                         break;
8769                 case 3 :
8770                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8771                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8772                         break;
8773                 case 4 :
8774                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8775                         break;
8776                 case 5 :
8777                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8778                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8779                         break;
8780                 case 6 :
8781                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8782                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8783                         break;
8784                 case 7 :
8785                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8786                         break;
8787         }
8788         if (doMask) {
8789                 /* no masking is required in genPackBits */
8790                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8791         }
8792 }
8793
8794 /*-----------------------------------------------------------------*/
8795 /* AccRsh - right shift accumulator by known count                 */
8796 /*-----------------------------------------------------------------*/
8797 static void AccRsh (int shCount, int andmask)
8798 {
8799         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8800         switch(shCount){
8801                 case 0 :
8802                         return; break;
8803                 case 1 :
8804                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8805                         break;
8806                 case 2 :
8807                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8808                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8809                         break;
8810                 case 3 :
8811                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8812                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8813                         break;
8814                 case 4 :
8815                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8816                         break;
8817                 case 5 :
8818                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8819                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8820                         break;
8821                 case 6 :
8822                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8823                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8824                         break;
8825                 case 7 :
8826                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8827                         break;
8828         }
8829         
8830         if(andmask)
8831                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8832         else
8833                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8834 }
8835
8836 #if 0
8837 /*-----------------------------------------------------------------*/
8838 /* AccSRsh - signed right shift accumulator by known count                 */
8839 /*-----------------------------------------------------------------*/
8840 static void AccSRsh (int shCount)
8841 {
8842     symbol *tlbl ;
8843     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8844     if(shCount != 0){
8845         if(shCount == 1){
8846             pic16_emitcode("mov","c,acc.7");
8847             pic16_emitcode("rrc","a");
8848         } else if(shCount == 2){
8849             pic16_emitcode("mov","c,acc.7");
8850             pic16_emitcode("rrc","a");
8851             pic16_emitcode("mov","c,acc.7");
8852             pic16_emitcode("rrc","a");
8853         } else {
8854             tlbl = newiTempLabel(NULL);
8855             /* rotate right accumulator */
8856             AccRol(8 - shCount);
8857             /* and kill the higher order bits */
8858             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8859             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8860             pic16_emitcode("orl","a,#0x%02x",
8861                      (unsigned char)~SRMask[shCount]);
8862             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8863         }
8864     }
8865 }
8866 #endif
8867
8868 /*-----------------------------------------------------------------*/
8869 /* shiftR1Left2Result - shift right one byte from left to result   */
8870 /*-----------------------------------------------------------------*/
8871 static void shiftR1Left2ResultSigned (operand *left, int offl,
8872                                 operand *result, int offr,
8873                                 int shCount)
8874 {
8875   int same;
8876
8877   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8878
8879   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8880
8881   switch(shCount) {
8882   case 1:
8883     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8884     if(same) 
8885       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8886     else {
8887       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8888       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8889     }
8890
8891     break;
8892   case 2:
8893
8894     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8895     if(same) 
8896       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8897     else {
8898       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8899       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8900     }
8901     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8902     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8903
8904     break;
8905
8906   case 3:
8907     if(same)
8908       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8909     else {
8910       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8911       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8912     }
8913
8914     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8915     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8916     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8917
8918     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8919     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8920
8921     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8922     break;
8923
8924   case 4:
8925     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8926     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8927     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8928     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8929     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8930     break;
8931   case 5:
8932     if(same) {
8933       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8934     } else {
8935       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8936       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8937     }
8938     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8939     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8940     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8941     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8942     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8943     break;
8944
8945   case 6:
8946     if(same) {
8947       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8948       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8949       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8950       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8951       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8952       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8953     } else {
8954       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8955       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8956       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8957       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8958       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8959     }
8960     break;
8961
8962   case 7:
8963     if(same) {
8964       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8965       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8966       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8967       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8968     } else {
8969       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8971       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8972     }
8973
8974   default:
8975     break;
8976   }
8977 }
8978
8979 /*-----------------------------------------------------------------*/
8980 /* shiftR1Left2Result - shift right one byte from left to result   */
8981 /*-----------------------------------------------------------------*/
8982 static void shiftR1Left2Result (operand *left, int offl,
8983                                 operand *result, int offr,
8984                                 int shCount, int sign)
8985 {
8986   int same;
8987
8988   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8989
8990   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8991
8992   /* Copy the msb into the carry if signed. */
8993   if(sign) {
8994     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8995     return;
8996   }
8997
8998
8999
9000   switch(shCount) {
9001   case 1:
9002     emitCLRC;
9003     if(same) 
9004       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9005     else {
9006       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9007       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9008     }
9009     break;
9010   case 2:
9011     emitCLRC;
9012     if(same) {
9013       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9014     } else {
9015       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9016       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9017     }
9018     emitCLRC;
9019     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9020
9021     break;
9022   case 3:
9023     if(same)
9024       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9025     else {
9026       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9027       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9028     }
9029
9030     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9031     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9032     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9033     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9034     break;
9035       
9036   case 4:
9037     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9038     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9039     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9040     break;
9041
9042   case 5:
9043     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9044     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9045     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9046     //emitCLRC;
9047     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9048
9049     break;
9050   case 6:
9051
9052     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9053     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9054     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9055     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9056     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9057     break;
9058
9059   case 7:
9060
9061     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9062     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9063     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9064
9065     break;
9066
9067   default:
9068     break;
9069   }
9070 }
9071
9072 /*-----------------------------------------------------------------*/
9073 /* shiftL1Left2Result - shift left one byte from left to result    */
9074 /*-----------------------------------------------------------------*/
9075 static void shiftL1Left2Result (operand *left, int offl,
9076                                 operand *result, int offr, int shCount)
9077 {
9078   int same;
9079
9080   //    char *l;
9081   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9082
9083   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9084   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9085     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9086     //    MOVA(l);
9087     /* shift left accumulator */
9088     //AccLsh(shCount, 1); // don't comment out just yet...
9089   //    pic16_aopPut(AOP(result),"a",offr);
9090
9091   switch(shCount) {
9092   case 1:
9093     /* Shift left 1 bit position */
9094     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9095     if(same) {
9096       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9097     } else {
9098       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9099       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9100     }
9101     break;
9102   case 2:
9103     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9104     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9105     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9106     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9107     break;
9108   case 3:
9109     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9110     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9111     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9112     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9113     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9114     break;
9115   case 4:
9116     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9117     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9118     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9119     break;
9120   case 5:
9121     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9122     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9123     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9124     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9125     break;
9126   case 6:
9127     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9128     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9129     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9130     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9131     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9132     break;
9133   case 7:
9134     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9135     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9136     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9137     break;
9138
9139   default:
9140     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9141   }
9142
9143 }
9144
9145 /*-----------------------------------------------------------------*/
9146 /* movLeft2Result - move byte from left to result                  */
9147 /*-----------------------------------------------------------------*/
9148 static void movLeft2Result (operand *left, int offl,
9149                             operand *result, int offr)
9150 {
9151   char *l;
9152   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9153   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9154     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9155
9156     if (*l == '@' && (IS_AOP_PREG(result))) {
9157       pic16_emitcode("mov","a,%s",l);
9158       pic16_aopPut(AOP(result),"a",offr);
9159     } else {
9160       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9161       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9162     }
9163   }
9164 }
9165
9166 /*-----------------------------------------------------------------*/
9167 /* shiftL2Left2Result - shift left two bytes from left to result   */
9168 /*-----------------------------------------------------------------*/
9169 static void shiftL2Left2Result (operand *left, int offl,
9170                                 operand *result, int offr, int shCount)
9171 {
9172   int same = pic16_sameRegs(AOP(result), AOP(left));
9173   int i;
9174
9175   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9176
9177   if (same && (offl != offr)) { // shift bytes
9178     if (offr > offl) {
9179        for(i=1;i>-1;i--) {
9180          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9181          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9182        }
9183     } else { // just treat as different later on
9184                 same = 0;
9185     }
9186   }
9187
9188   if(same) {
9189     switch(shCount) {
9190     case 0:
9191       break;
9192     case 1:
9193     case 2:
9194     case 3:
9195
9196       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9197       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9198       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9199
9200       while(--shCount) {
9201                 emitCLRC;
9202                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9203                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9204       }
9205
9206       break;
9207     case 4:
9208     case 5:
9209       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9210       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9211       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9212       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9213       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9214       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9215       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9216       if(shCount >=5) {
9217                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9218                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9219       }
9220       break;
9221     case 6:
9222       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9223       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9224       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9225       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9226       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9227       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9228       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9229       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9230       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9231       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9232       break;
9233     case 7:
9234       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9235       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9236       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9237       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9238       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9239     }
9240
9241   } else {
9242     switch(shCount) {
9243     case 0:
9244       break;
9245     case 1:
9246     case 2:
9247     case 3:
9248       /* note, use a mov/add for the shift since the mov has a
9249          chance of getting optimized out */
9250       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9251       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9252       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9253       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9254       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9255
9256       while(--shCount) {
9257                 emitCLRC;
9258                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9259                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9260       }
9261       break;
9262
9263     case 4:
9264     case 5:
9265       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9266       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9267       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9268       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9269       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9270       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9271       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9272       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9273
9274
9275       if(shCount == 5) {
9276                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9277                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9278       }
9279       break;
9280     case 6:
9281       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9282       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9283       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9284       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9285
9286       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9287       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9288       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9289       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9290       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9291       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9292       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9293       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9294       break;
9295     case 7:
9296       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9297       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9298       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9299       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9300       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9301     }
9302   }
9303
9304 }
9305 /*-----------------------------------------------------------------*/
9306 /* shiftR2Left2Result - shift right two bytes from left to result  */
9307 /*-----------------------------------------------------------------*/
9308 static void shiftR2Left2Result (operand *left, int offl,
9309                                 operand *result, int offr,
9310                                 int shCount, int sign)
9311 {
9312   int same = pic16_sameRegs(AOP(result), AOP(left));
9313   int i;
9314   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9315
9316   if (same && (offl != offr)) { // shift right bytes
9317     if (offr < offl) {
9318        for(i=0;i<2;i++) {
9319          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9320          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9321        }
9322     } else { // just treat as different later on
9323                 same = 0;
9324     }
9325   }
9326
9327   switch(shCount) {
9328   case 0:
9329     break;
9330   case 1:
9331   case 2:
9332   case 3:
9333     /* obtain sign from left operand */
9334     if(sign)
9335       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9336     else
9337       emitCLRC;
9338
9339     if(same) {
9340       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9341       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9342     } else {
9343       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9344       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9345       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9346       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9347     }
9348
9349     while(--shCount) {
9350       if(sign)
9351         /* now get sign from already assigned result (avoid BANKSEL) */
9352         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9353       else
9354         emitCLRC;
9355       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9356       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9357     }
9358     break;
9359   case 4:
9360   case 5:
9361     if(same) {
9362
9363       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9364       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9365       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9366
9367       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9368       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9369       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9370       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9371     } else {
9372       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9373       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9374       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9375
9376       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9377       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9378       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9379       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9380       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9381     }
9382
9383     if(shCount >=5) {
9384       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9385       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9386     }
9387
9388     if(sign) {
9389       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9390       pic16_emitpcode(POC_BTFSC, 
9391                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9392       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9393     }
9394
9395     break;
9396
9397   case 6:
9398     if(same) {
9399
9400       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9401       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9402
9403       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9404       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9405       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9406       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9407       if(sign) {
9408         pic16_emitpcode(POC_BTFSC, 
9409                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9410         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9411       }
9412       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9413       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9414       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9415       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9416     } else {
9417       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9418       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9419       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9420       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9421       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9422       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9423       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9424       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9425       if(sign) {
9426         pic16_emitpcode(POC_BTFSC, 
9427                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9428         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9429       }
9430       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9431       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9432
9433         
9434     }
9435
9436     break;
9437   case 7:
9438     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9439     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9440     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9441     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9442     if(sign) {
9443       emitSKPNC;
9444       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9445     } else 
9446       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9447   }
9448 }
9449
9450
9451 /*-----------------------------------------------------------------*/
9452 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9453 /*-----------------------------------------------------------------*/
9454 static void shiftLLeftOrResult (operand *left, int offl,
9455                                 operand *result, int offr, int shCount)
9456 {
9457     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9458
9459     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9460     /* shift left accumulator */
9461     AccLsh(shCount, 1);
9462     /* or with result */
9463     /* back to result */
9464     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9465 }
9466
9467 /*-----------------------------------------------------------------*/
9468 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9469 /*-----------------------------------------------------------------*/
9470 static void shiftRLeftOrResult (operand *left, int offl,
9471                                 operand *result, int offr, int shCount)
9472 {
9473     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9474     
9475     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9476     /* shift right accumulator */
9477     AccRsh(shCount, 1);
9478     /* or with result */
9479     /* back to result */
9480     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9481 }
9482
9483 /*-----------------------------------------------------------------*/
9484 /* genlshOne - left shift a one byte quantity by known count       */
9485 /*-----------------------------------------------------------------*/
9486 static void genlshOne (operand *result, operand *left, int shCount)
9487 {       
9488     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9489     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9490 }
9491
9492 /*-----------------------------------------------------------------*/
9493 /* genlshTwo - left shift two bytes by known amount != 0           */
9494 /*-----------------------------------------------------------------*/
9495 static void genlshTwo (operand *result,operand *left, int shCount)
9496 {
9497     int size;
9498     
9499     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9500     size = pic16_getDataSize(result);
9501
9502     /* if shCount >= 8 */
9503     if (shCount >= 8) {
9504         shCount -= 8 ;
9505
9506         if (size > 1){
9507             if (shCount)
9508                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9509             else 
9510                 movLeft2Result(left, LSB, result, MSB16);
9511         }
9512         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9513     }
9514
9515     /*  1 <= shCount <= 7 */
9516     else {  
9517         if(size == 1)
9518             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9519         else 
9520             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9521     }
9522 }
9523
9524 /*-----------------------------------------------------------------*/
9525 /* shiftLLong - shift left one long from left to result            */
9526 /* offr = LSB or MSB16                                             */
9527 /*-----------------------------------------------------------------*/
9528 static void shiftLLong (operand *left, operand *result, int offr )
9529 {
9530     int size = AOP_SIZE(result);
9531     int same = pic16_sameRegs(AOP(left),AOP(result));
9532         int i;
9533
9534     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9535
9536         if (same && (offr == MSB16)) { //shift one byte
9537                 for(i=size-1;i>=MSB16;i--) {
9538                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9539                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9540                 }
9541         } else {
9542                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9543         }
9544         
9545     if (size > LSB+offr ){
9546                 if (same) {
9547                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9548                 } else {
9549                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9550                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9551                 }
9552          }
9553
9554     if(size > MSB16+offr){
9555                 if (same) {
9556                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9557                 } else {
9558                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9559                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9560                 }
9561     }
9562
9563     if(size > MSB24+offr){
9564                 if (same) {
9565                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9566                 } else {
9567                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9568                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9569                 }
9570     }
9571
9572     if(size > MSB32+offr){
9573                 if (same) {
9574                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9575                 } else {
9576                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9577                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9578                 }
9579     }
9580     if(offr != LSB)
9581                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9582
9583 }
9584
9585 /*-----------------------------------------------------------------*/
9586 /* genlshFour - shift four byte by a known amount != 0             */
9587 /*-----------------------------------------------------------------*/
9588 static void genlshFour (operand *result, operand *left, int shCount)
9589 {
9590     int size;
9591
9592     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9593     size = AOP_SIZE(result);
9594
9595     /* if shifting more that 3 bytes */
9596     if (shCount >= 24 ) {
9597         shCount -= 24;
9598         if (shCount)
9599             /* lowest order of left goes to the highest
9600             order of the destination */
9601             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9602         else
9603             movLeft2Result(left, LSB, result, MSB32);
9604
9605                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9606                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9607                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9608
9609         return;
9610     }
9611
9612     /* more than two bytes */
9613     else if ( shCount >= 16 ) {
9614         /* lower order two bytes goes to higher order two bytes */
9615         shCount -= 16;
9616         /* if some more remaining */
9617         if (shCount)
9618             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9619         else {
9620             movLeft2Result(left, MSB16, result, MSB32);
9621             movLeft2Result(left, LSB, result, MSB24);
9622         }
9623                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9624                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9625         return;
9626     }    
9627
9628     /* if more than 1 byte */
9629     else if ( shCount >= 8 ) {
9630         /* lower order three bytes goes to higher order  three bytes */
9631         shCount -= 8;
9632         if(size == 2){
9633             if(shCount)
9634                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9635             else
9636                 movLeft2Result(left, LSB, result, MSB16);
9637         }
9638         else{   /* size = 4 */
9639             if(shCount == 0){
9640                 movLeft2Result(left, MSB24, result, MSB32);
9641                 movLeft2Result(left, MSB16, result, MSB24);
9642                 movLeft2Result(left, LSB, result, MSB16);
9643                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9644             }
9645             else if(shCount == 1)
9646                 shiftLLong(left, result, MSB16);
9647             else{
9648                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9649                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9650                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9651                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9652             }
9653         }
9654     }
9655
9656     /* 1 <= shCount <= 7 */
9657     else if(shCount <= 3)
9658     { 
9659         shiftLLong(left, result, LSB);
9660         while(--shCount >= 1)
9661             shiftLLong(result, result, LSB);
9662     }
9663     /* 3 <= shCount <= 7, optimize */
9664     else{
9665         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9666         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9667         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9668     }
9669 }
9670
9671 /*-----------------------------------------------------------------*/
9672 /* genLeftShiftLiteral - left shifting by known count              */
9673 /*-----------------------------------------------------------------*/
9674 void pic16_genLeftShiftLiteral (operand *left,
9675                                  operand *right,
9676                                  operand *result,
9677                                  iCode *ic)
9678 {    
9679     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9680     int size;
9681
9682     FENTRY;
9683     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9684     pic16_freeAsmop(right,NULL,ic,TRUE);
9685
9686     pic16_aopOp(left,ic,FALSE);
9687     pic16_aopOp(result,ic,TRUE);
9688
9689     size = getSize(operandType(result));
9690
9691 #if VIEW_SIZE
9692     pic16_emitcode("; shift left ","result %d, left %d",size,
9693              AOP_SIZE(left));
9694 #endif
9695
9696     /* I suppose that the left size >= result size */
9697     if(shCount == 0){
9698         while(size--){
9699             movLeft2Result(left, size, result, size);
9700         }
9701     }
9702
9703     else if(shCount >= (size * 8))
9704         while(size--)
9705             pic16_aopPut(AOP(result),zero,size);
9706     else{
9707         switch (size) {
9708             case 1:
9709                 genlshOne (result,left,shCount);
9710                 break;
9711
9712             case 2:
9713             case 3:
9714                 genlshTwo (result,left,shCount);
9715                 break;
9716
9717             case 4:
9718                 genlshFour (result,left,shCount);
9719                 break;
9720         }
9721     }
9722     pic16_freeAsmop(left,NULL,ic,TRUE);
9723     pic16_freeAsmop(result,NULL,ic,TRUE);
9724 }
9725
9726 /*-----------------------------------------------------------------*
9727  * genMultiAsm - repeat assembly instruction for size of register.
9728  * if endian == 1, then the high byte (i.e base address + size of 
9729  * register) is used first else the low byte is used first;
9730  *-----------------------------------------------------------------*/
9731 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9732 {
9733
9734   int offset = 0;
9735
9736   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9737
9738   if(!reg)
9739     return;
9740
9741   if(!endian) {
9742     endian = 1;
9743   } else {
9744     endian = -1;
9745     offset = size-1;
9746   }
9747
9748   while(size--) {
9749     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9750     offset += endian;
9751   }
9752
9753 }
9754
9755 #if !(USE_GENERIC_SIGNED_SHIFT)
9756 /*-----------------------------------------------------------------*/
9757 /* genLeftShift - generates code for left shifting                 */
9758 /*-----------------------------------------------------------------*/
9759 static void genLeftShift (iCode *ic)
9760 {
9761   operand *left,*right, *result;
9762   int size, offset;
9763 //  char *l;
9764   symbol *tlbl , *tlbl1;
9765   pCodeOp *pctemp;
9766
9767   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9768
9769   right = IC_RIGHT(ic);
9770   left  = IC_LEFT(ic);
9771   result = IC_RESULT(ic);
9772
9773   pic16_aopOp(right,ic,FALSE);
9774
9775   /* if the shift count is known then do it 
9776      as efficiently as possible */
9777   if (AOP_TYPE(right) == AOP_LIT) {
9778     pic16_genLeftShiftLiteral (left,right,result,ic);
9779     return ;
9780   }
9781
9782   /* shift count is unknown then we have to form
9783    * a loop. Get the loop count in WREG : Note: we take
9784    * only the lower order byte since shifting
9785    * more than 32 bits make no sense anyway, ( the
9786    * largest size of an object can be only 32 bits ) */
9787   
9788   pic16_aopOp(left,ic,FALSE);
9789   pic16_aopOp(result,ic,FALSE);
9790
9791   /* now move the left to the result if they are not the
9792    * same, and if size > 1,
9793    * and if right is not same to result (!!!) -- VR */
9794   if (!pic16_sameRegs(AOP(left),AOP(result))
9795       && (AOP_SIZE(result) > 1)) {
9796
9797     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9798
9799     size = AOP_SIZE(result);
9800     offset=0;
9801     while (size--) {
9802
9803 #if 0
9804       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9805       if (*l == '@' && (IS_AOP_PREG(result))) {
9806
9807           pic16_emitcode("mov","a,%s",l);
9808           pic16_aopPut(AOP(result),"a",offset);
9809       } else
9810 #endif
9811       {
9812         /* we don't know if left is a literal or a register, take care -- VR */
9813         pic16_mov2f(AOP(result), AOP(left), offset);
9814       }
9815       offset++;
9816     }
9817   }
9818
9819   size = AOP_SIZE(result);
9820
9821   /* if it is only one byte then */
9822   if (size == 1) {
9823     if(optimized_for_speed) {
9824       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9825       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9826       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9827       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9828       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9829       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9830       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9831       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9832       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9833       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9834       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9835       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9836     } else {
9837
9838       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9839
9840       tlbl = newiTempLabel(NULL);
9841
9842 #if 1
9843       /* this is already done, why change it? */
9844       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9845                 pic16_mov2f(AOP(result), AOP(left), 0);
9846       }
9847 #endif
9848
9849       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9850       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9851       pic16_emitpLabel(tlbl->key);
9852       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9853       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9854       emitSKPC;
9855       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9856     }
9857     goto release ;
9858   }
9859     
9860   if (pic16_sameRegs(AOP(left),AOP(result))) {
9861
9862     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9863     
9864     tlbl = newiTempLabel(NULL);
9865     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9866     genMultiAsm(POC_RRCF, result, size,1);
9867     pic16_emitpLabel(tlbl->key);
9868     genMultiAsm(POC_RLCF, result, size,0);
9869     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9870     emitSKPC;
9871     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9872     goto release;
9873   }
9874
9875   //tlbl = newiTempLabel(NULL);
9876   //offset = 0 ;   
9877   //tlbl1 = newiTempLabel(NULL);
9878
9879   //reAdjustPreg(AOP(result));    
9880     
9881   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9882   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9883   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9884   //MOVA(l);
9885   //pic16_emitcode("add","a,acc");         
9886   //pic16_aopPut(AOP(result),"a",offset++);
9887   //while (--size) {
9888   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9889   //  MOVA(l);
9890   //  pic16_emitcode("rlc","a");         
9891   //  pic16_aopPut(AOP(result),"a",offset++);
9892   //}
9893   //reAdjustPreg(AOP(result));
9894
9895   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9896   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9897
9898
9899   tlbl = newiTempLabel(NULL);
9900   tlbl1= newiTempLabel(NULL);
9901
9902   size = AOP_SIZE(result);
9903   offset = 1;
9904
9905   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9906
9907   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9908
9909   /* offset should be 0, 1 or 3 */
9910   
9911   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9912   emitSKPNZ;
9913   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9914
9915   pic16_emitpcode(POC_MOVWF, pctemp);
9916
9917
9918   pic16_emitpLabel(tlbl->key);
9919
9920   emitCLRC;
9921   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9922   while(--size)
9923     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9924
9925   pic16_emitpcode(POC_DECFSZ,  pctemp);
9926   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9927   pic16_emitpLabel(tlbl1->key);
9928
9929   pic16_popReleaseTempReg(pctemp,1);
9930
9931
9932  release:
9933   pic16_freeAsmop (right,NULL,ic,TRUE);
9934   pic16_freeAsmop(left,NULL,ic,TRUE);
9935   pic16_freeAsmop(result,NULL,ic,TRUE);
9936 }
9937 #endif
9938
9939
9940 #if 0
9941 #error old code (left here for reference)
9942 /*-----------------------------------------------------------------*/
9943 /* genLeftShift - generates code for left shifting                 */
9944 /*-----------------------------------------------------------------*/
9945 static void genLeftShift (iCode *ic)
9946 {
9947   operand *left,*right, *result;
9948   int size, offset;
9949   char *l;
9950   symbol *tlbl , *tlbl1;
9951   pCodeOp *pctemp;
9952
9953   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9954
9955   right = IC_RIGHT(ic);
9956   left  = IC_LEFT(ic);
9957   result = IC_RESULT(ic);
9958
9959   pic16_aopOp(right,ic,FALSE);
9960
9961   /* if the shift count is known then do it 
9962      as efficiently as possible */
9963   if (AOP_TYPE(right) == AOP_LIT) {
9964     pic16_genLeftShiftLiteral (left,right,result,ic);
9965     return ;
9966   }
9967
9968   /* shift count is unknown then we have to form 
9969      a loop get the loop count in B : Note: we take
9970      only the lower order byte since shifting
9971      more that 32 bits make no sense anyway, ( the
9972      largest size of an object can be only 32 bits ) */  
9973
9974     
9975   pic16_aopOp(left,ic,FALSE);
9976   pic16_aopOp(result,ic,FALSE);
9977
9978   /* now move the left to the result if they are not the
9979      same */
9980   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9981       AOP_SIZE(result) > 1) {
9982
9983     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9984
9985     size = AOP_SIZE(result);
9986     offset=0;
9987     while (size--) {
9988       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9989       if (*l == '@' && (IS_AOP_PREG(result))) {
9990
9991         pic16_emitcode("mov","a,%s",l);
9992         pic16_aopPut(AOP(result),"a",offset);
9993       } else {
9994
9995         /* we don't know if left is a literal or a register, take care -- VR */
9996         pic16_mov2f(AOP(result), AOP(left), offset);
9997       }
9998       offset++;
9999     }
10000   }
10001
10002   size = AOP_SIZE(result);
10003
10004   /* if it is only one byte then */
10005   if (size == 1) {
10006     if(optimized_for_speed) {
10007       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10008       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10009       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10010       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10011       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10012       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10013       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10014       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10015       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10016       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10017       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10018       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10019     } else {
10020
10021       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10022
10023       tlbl = newiTempLabel(NULL);
10024       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10025                 pic16_mov2f(AOP(result), AOP(left), 0);
10026                 
10027 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10028 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10029       }
10030
10031       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10032       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10033       pic16_emitpLabel(tlbl->key);
10034       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10035       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10036       emitSKPC;
10037       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10038     }
10039     goto release ;
10040   }
10041     
10042   if (pic16_sameRegs(AOP(left),AOP(result))) {
10043
10044     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10045     
10046     tlbl = newiTempLabel(NULL);
10047     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10048     genMultiAsm(POC_RRCF, result, size,1);
10049     pic16_emitpLabel(tlbl->key);
10050     genMultiAsm(POC_RLCF, result, size,0);
10051     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10052     emitSKPC;
10053     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10054     goto release;
10055   }
10056
10057   //tlbl = newiTempLabel(NULL);
10058   //offset = 0 ;   
10059   //tlbl1 = newiTempLabel(NULL);
10060
10061   //reAdjustPreg(AOP(result));    
10062     
10063   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10064   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10065   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10066   //MOVA(l);
10067   //pic16_emitcode("add","a,acc");         
10068   //pic16_aopPut(AOP(result),"a",offset++);
10069   //while (--size) {
10070   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10071   //  MOVA(l);
10072   //  pic16_emitcode("rlc","a");         
10073   //  pic16_aopPut(AOP(result),"a",offset++);
10074   //}
10075   //reAdjustPreg(AOP(result));
10076
10077   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10078   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10079
10080
10081   tlbl = newiTempLabel(NULL);
10082   tlbl1= newiTempLabel(NULL);
10083
10084   size = AOP_SIZE(result);
10085   offset = 1;
10086
10087   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10088
10089   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10090
10091   /* offset should be 0, 1 or 3 */
10092   
10093   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10094   emitSKPNZ;
10095   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10096
10097   pic16_emitpcode(POC_MOVWF, pctemp);
10098
10099
10100   pic16_emitpLabel(tlbl->key);
10101
10102   emitCLRC;
10103   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10104   while(--size)
10105     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10106
10107   pic16_emitpcode(POC_DECFSZ,  pctemp);
10108   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10109   pic16_emitpLabel(tlbl1->key);
10110
10111   pic16_popReleaseTempReg(pctemp,1);
10112
10113
10114  release:
10115   pic16_freeAsmop (right,NULL,ic,TRUE);
10116   pic16_freeAsmop(left,NULL,ic,TRUE);
10117   pic16_freeAsmop(result,NULL,ic,TRUE);
10118 }
10119 #endif
10120
10121 /*-----------------------------------------------------------------*/
10122 /* genrshOne - right shift a one byte quantity by known count      */
10123 /*-----------------------------------------------------------------*/
10124 static void genrshOne (operand *result, operand *left,
10125                        int shCount, int sign)
10126 {
10127     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10128     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10129 }
10130
10131 /*-----------------------------------------------------------------*/
10132 /* genrshTwo - right shift two bytes by known amount != 0          */
10133 /*-----------------------------------------------------------------*/
10134 static void genrshTwo (operand *result,operand *left,
10135                        int shCount, int sign)
10136 {
10137   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10138   /* if shCount >= 8 */
10139   if (shCount >= 8) {
10140     shCount -= 8 ;
10141     if (shCount)
10142       shiftR1Left2Result(left, MSB16, result, LSB,
10143                          shCount, sign);
10144     else
10145       movLeft2Result(left, MSB16, result, LSB);
10146
10147     pic16_addSign (result, 1, sign);
10148   }
10149
10150   /*  1 <= shCount <= 7 */
10151   else
10152     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10153 }
10154
10155 /*-----------------------------------------------------------------*/
10156 /* shiftRLong - shift right one long from left to result           */
10157 /* offl = LSB or MSB16                                             */
10158 /*-----------------------------------------------------------------*/
10159 static void shiftRLong (operand *left, int offl,
10160                         operand *result, int sign)
10161 {
10162     int size = AOP_SIZE(result);
10163     int same = pic16_sameRegs(AOP(left),AOP(result));
10164     int i;
10165     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10166
10167         if (same && (offl == MSB16)) { //shift one byte right
10168                 for(i=MSB16;i<size;i++) {
10169                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10170                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10171                 }
10172         }
10173
10174     if(sign)
10175                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10176         else
10177                 emitCLRC;
10178
10179         if (same) {
10180                 if (offl == LSB)
10181                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10182         } else {
10183         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10184         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10185         }
10186
10187     if(offl == MSB16) {
10188         /* add sign of "a" */
10189         pic16_addSign(result, MSB32, sign);
10190         }
10191
10192         if (same) {
10193         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10194         } else {
10195         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10196         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10197         }
10198         
10199         if (same) {
10200         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10201         } else {
10202         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10203         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10204         }
10205
10206         if (same) {
10207         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10208         } else {
10209         if(offl == LSB){
10210                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10211                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10212         }
10213         }
10214 }
10215
10216 /*-----------------------------------------------------------------*/
10217 /* genrshFour - shift four byte by a known amount != 0             */
10218 /*-----------------------------------------------------------------*/
10219 static void genrshFour (operand *result, operand *left,
10220                         int shCount, int sign)
10221 {
10222   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10223   /* if shifting more that 3 bytes */
10224   if(shCount >= 24 ) {
10225     shCount -= 24;
10226     if(shCount)
10227       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10228     else
10229       movLeft2Result(left, MSB32, result, LSB);
10230
10231     pic16_addSign(result, MSB16, sign);
10232   }
10233   else if(shCount >= 16){
10234     shCount -= 16;
10235     if(shCount)
10236       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10237     else{
10238       movLeft2Result(left, MSB24, result, LSB);
10239       movLeft2Result(left, MSB32, result, MSB16);
10240     }
10241     pic16_addSign(result, MSB24, sign);
10242   }
10243   else if(shCount >= 8){
10244     shCount -= 8;
10245     if(shCount == 1)
10246       shiftRLong(left, MSB16, result, sign);
10247     else if(shCount == 0){
10248       movLeft2Result(left, MSB16, result, LSB);
10249       movLeft2Result(left, MSB24, result, MSB16);
10250       movLeft2Result(left, MSB32, result, MSB24);
10251       pic16_addSign(result, MSB32, sign);
10252     }
10253     else{ //shcount >= 2
10254       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10255       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10256       /* the last shift is signed */
10257       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10258       pic16_addSign(result, MSB32, sign);
10259     }
10260   }
10261   else{   /* 1 <= shCount <= 7 */
10262     if(shCount <= 2){
10263       shiftRLong(left, LSB, result, sign);
10264       if(shCount == 2)
10265         shiftRLong(result, LSB, result, sign);
10266     }
10267     else{
10268       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10269       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10270       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10271     }
10272   }
10273 }
10274
10275 /*-----------------------------------------------------------------*/
10276 /* genRightShiftLiteral - right shifting by known count            */
10277 /*-----------------------------------------------------------------*/
10278 static void genRightShiftLiteral (operand *left,
10279                                   operand *right,
10280                                   operand *result,
10281                                   iCode *ic,
10282                                   int sign)
10283 {    
10284   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10285   int lsize,res_size;
10286
10287   pic16_freeAsmop(right,NULL,ic,TRUE);
10288
10289   pic16_aopOp(left,ic,FALSE);
10290   pic16_aopOp(result,ic,TRUE);
10291
10292   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10293
10294 #if VIEW_SIZE
10295   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10296                  AOP_SIZE(left));
10297 #endif
10298
10299   lsize = pic16_getDataSize(left);
10300   res_size = pic16_getDataSize(result);
10301   /* test the LEFT size !!! */
10302
10303   /* I suppose that the left size >= result size */
10304   if(shCount == 0){
10305     assert (res_size <= lsize);
10306     while (res_size--) {
10307       pic16_mov2f (AOP(result), AOP(left), res_size);
10308     } // for
10309   }
10310
10311   else if(shCount >= (lsize * 8)){
10312
10313     if(res_size == 1) {
10314       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10315       if(sign) {
10316         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10317         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10318       }
10319     } else {
10320
10321       if(sign) {
10322         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10323         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10324         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10325         while(res_size--)
10326           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10327
10328       } else {
10329
10330         while(res_size--)
10331           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10332       }
10333     }
10334   } else {
10335
10336     switch (res_size) {
10337     case 1:
10338       genrshOne (result,left,shCount,sign);
10339       break;
10340
10341     case 2:
10342       genrshTwo (result,left,shCount,sign);
10343       break;
10344
10345     case 4:
10346       genrshFour (result,left,shCount,sign);
10347       break;
10348     default :
10349       break;
10350     }
10351
10352   }
10353
10354   pic16_freeAsmop(left,NULL,ic,TRUE);
10355   pic16_freeAsmop(result,NULL,ic,TRUE);
10356 }
10357
10358 #if !(USE_GENERIC_SIGNED_SHIFT)
10359 /*-----------------------------------------------------------------*/
10360 /* genSignedRightShift - right shift of signed number              */
10361 /*-----------------------------------------------------------------*/
10362 static void genSignedRightShift (iCode *ic)
10363 {
10364   operand *right, *left, *result;
10365   int size, offset;
10366   //  char *l;
10367   symbol *tlbl, *tlbl1 ;
10368   pCodeOp *pctemp;
10369
10370   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10371
10372   /* we do it the hard way put the shift count in b
10373      and loop thru preserving the sign */
10374   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10375
10376   right = IC_RIGHT(ic);
10377   left  = IC_LEFT(ic);
10378   result = IC_RESULT(ic);
10379
10380   pic16_aopOp(right,ic,FALSE);  
10381   pic16_aopOp(left,ic,FALSE);
10382   pic16_aopOp(result,ic,FALSE);
10383
10384
10385   if ( AOP_TYPE(right) == AOP_LIT) {
10386     genRightShiftLiteral (left,right,result,ic,1);
10387     return ;
10388   }
10389   /* shift count is unknown then we have to form 
10390      a loop get the loop count in B : Note: we take
10391      only the lower order byte since shifting
10392      more that 32 bits make no sense anyway, ( the
10393      largest size of an object can be only 32 bits ) */  
10394
10395   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10396   //pic16_emitcode("inc","b");
10397   //pic16_freeAsmop (right,NULL,ic,TRUE);
10398   //pic16_aopOp(left,ic,FALSE);
10399   //pic16_aopOp(result,ic,FALSE);
10400
10401   /* now move the left to the result if they are not the
10402      same */
10403   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10404       AOP_SIZE(result) > 1) {
10405
10406     size = AOP_SIZE(result);
10407     offset=0;
10408     while (size--) { 
10409       /*
10410         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10411         if (*l == '@' && IS_AOP_PREG(result)) {
10412
10413         pic16_emitcode("mov","a,%s",l);
10414         pic16_aopPut(AOP(result),"a",offset);
10415         } else
10416         pic16_aopPut(AOP(result),l,offset);
10417       */
10418       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10419       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10420
10421       offset++;
10422     }
10423   }
10424
10425   /* mov the highest order bit to OVR */    
10426   tlbl = newiTempLabel(NULL);
10427   tlbl1= newiTempLabel(NULL);
10428
10429   size = AOP_SIZE(result);
10430   offset = size - 1;
10431
10432   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10433
10434   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10435
10436   /* offset should be 0, 1 or 3 */
10437   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10438   emitSKPNZ;
10439   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10440
10441   pic16_emitpcode(POC_MOVWF, pctemp);
10442
10443
10444   pic16_emitpLabel(tlbl->key);
10445
10446   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10447   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10448
10449   while(--size) {
10450     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10451   }
10452
10453   pic16_emitpcode(POC_DECFSZ,  pctemp);
10454   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10455   pic16_emitpLabel(tlbl1->key);
10456
10457   pic16_popReleaseTempReg(pctemp,1);
10458 #if 0
10459   size = AOP_SIZE(result);
10460   offset = size - 1;
10461   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10462   pic16_emitcode("rlc","a");
10463   pic16_emitcode("mov","ov,c");
10464   /* if it is only one byte then */
10465   if (size == 1) {
10466     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10467     MOVA(l);
10468     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10469     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10470     pic16_emitcode("mov","c,ov");
10471     pic16_emitcode("rrc","a");
10472     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10473     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10474     pic16_aopPut(AOP(result),"a",0);
10475     goto release ;
10476   }
10477
10478   reAdjustPreg(AOP(result));
10479   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10480   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10481   pic16_emitcode("mov","c,ov");
10482   while (size--) {
10483     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10484     MOVA(l);
10485     pic16_emitcode("rrc","a");         
10486     pic16_aopPut(AOP(result),"a",offset--);
10487   }
10488   reAdjustPreg(AOP(result));
10489   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10490   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10491
10492  release:
10493 #endif
10494
10495   pic16_freeAsmop(left,NULL,ic,TRUE);
10496   pic16_freeAsmop(result,NULL,ic,TRUE);
10497   pic16_freeAsmop(right,NULL,ic,TRUE);
10498 }
10499 #endif
10500
10501 #if !(USE_GENERIC_SIGNED_SHIFT)
10502 #warning This implementation of genRightShift() is incomplete!
10503 /*-----------------------------------------------------------------*/
10504 /* genRightShift - generate code for right shifting                */
10505 /*-----------------------------------------------------------------*/
10506 static void genRightShift (iCode *ic)
10507 {
10508     operand *right, *left, *result;
10509     sym_link *letype ;
10510     int size, offset;
10511     char *l;
10512     symbol *tlbl, *tlbl1 ;
10513
10514     /* if signed then we do it the hard way preserve the
10515     sign bit moving it inwards */
10516     letype = getSpec(operandType(IC_LEFT(ic)));
10517     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10518
10519     if (!SPEC_USIGN(letype)) {
10520         genSignedRightShift (ic);
10521         return ;
10522     }
10523
10524     /* signed & unsigned types are treated the same : i.e. the
10525     signed is NOT propagated inwards : quoting from the
10526     ANSI - standard : "for E1 >> E2, is equivalent to division
10527     by 2**E2 if unsigned or if it has a non-negative value,
10528     otherwise the result is implementation defined ", MY definition
10529     is that the sign does not get propagated */
10530
10531     right = IC_RIGHT(ic);
10532     left  = IC_LEFT(ic);
10533     result = IC_RESULT(ic);
10534
10535     pic16_aopOp(right,ic,FALSE);
10536
10537     /* if the shift count is known then do it 
10538     as efficiently as possible */
10539     if (AOP_TYPE(right) == AOP_LIT) {
10540         genRightShiftLiteral (left,right,result,ic, 0);
10541         return ;
10542     }
10543
10544     /* shift count is unknown then we have to form 
10545     a loop get the loop count in B : Note: we take
10546     only the lower order byte since shifting
10547     more that 32 bits make no sense anyway, ( the
10548     largest size of an object can be only 32 bits ) */  
10549
10550     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10551     pic16_emitcode("inc","b");
10552     pic16_aopOp(left,ic,FALSE);
10553     pic16_aopOp(result,ic,FALSE);
10554
10555     /* now move the left to the result if they are not the
10556     same */
10557     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10558         AOP_SIZE(result) > 1) {
10559
10560         size = AOP_SIZE(result);
10561         offset=0;
10562         while (size--) {
10563             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10564             if (*l == '@' && IS_AOP_PREG(result)) {
10565
10566                 pic16_emitcode("mov","a,%s",l);
10567                 pic16_aopPut(AOP(result),"a",offset);
10568             } else
10569                 pic16_aopPut(AOP(result),l,offset);
10570             offset++;
10571         }
10572     }
10573
10574     tlbl = newiTempLabel(NULL);
10575     tlbl1= newiTempLabel(NULL);
10576     size = AOP_SIZE(result);
10577     offset = size - 1;
10578
10579     /* if it is only one byte then */
10580     if (size == 1) {
10581
10582       tlbl = newiTempLabel(NULL);
10583       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10584         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10585         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10586       }
10587
10588       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10589       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10590       pic16_emitpLabel(tlbl->key);
10591       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10592       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10593       emitSKPC;
10594       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10595
10596       goto release ;
10597     }
10598
10599     reAdjustPreg(AOP(result));
10600     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10601     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10602     CLRC;
10603     while (size--) {
10604         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10605         MOVA(l);
10606         pic16_emitcode("rrc","a");         
10607         pic16_aopPut(AOP(result),"a",offset--);
10608     }
10609     reAdjustPreg(AOP(result));
10610
10611     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10612     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10613
10614 release:
10615     pic16_freeAsmop(left,NULL,ic,TRUE);
10616     pic16_freeAsmop (right,NULL,ic,TRUE);
10617     pic16_freeAsmop(result,NULL,ic,TRUE);
10618 }
10619 #endif
10620
10621 #if (USE_GENERIC_SIGNED_SHIFT)
10622 /*-----------------------------------------------------------------*/
10623 /* genGenericShift - generates code for left or right shifting     */
10624 /*-----------------------------------------------------------------*/
10625 static void genGenericShift (iCode *ic, int isShiftLeft) {
10626   operand *left,*right, *result;
10627   int offset;
10628   int sign, signedCount;
10629   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10630   PIC_OPCODE pos_shift, neg_shift;
10631
10632   FENTRY;
10633
10634   right = IC_RIGHT(ic);
10635   left  = IC_LEFT(ic);
10636   result = IC_RESULT(ic);
10637
10638   pic16_aopOp(right,ic,FALSE);
10639   pic16_aopOp(left,ic,FALSE);
10640   pic16_aopOp(result,ic,TRUE);
10641
10642   sign = !SPEC_USIGN(operandType (left));
10643   signedCount = !SPEC_USIGN(operandType (right));
10644
10645   /* if the shift count is known then do it 
10646      as efficiently as possible */
10647   if (AOP_TYPE(right) == AOP_LIT) {
10648     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10649     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10650     // we should modify right->aopu.aop_lit here!
10651     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10652     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10653     if (isShiftLeft)
10654       pic16_genLeftShiftLiteral (left,right,result,ic);
10655     else
10656       genRightShiftLiteral (left,right,result,ic, sign);
10657
10658     goto release;
10659   } // if (right is literal)
10660
10661   /* shift count is unknown then we have to form a loop.
10662    * Note: we take only the lower order byte since shifting
10663    * more than 32 bits make no sense anyway, ( the
10664    * largest size of an object can be only 32 bits )
10665    * Note: we perform arithmetic shifts if the left operand is
10666    * signed and we do an (effective) right shift, i. e. we
10667    * shift in the sign bit from the left. */
10668    
10669   label_complete = newiTempLabel ( NULL );
10670   label_loop_pos = newiTempLabel ( NULL );
10671   label_loop_neg = NULL;
10672   label_negative = NULL;
10673   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10674   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10675
10676   if (signedCount) {
10677     // additional labels needed
10678     label_loop_neg = newiTempLabel ( NULL );
10679     label_negative = newiTempLabel ( NULL );
10680   } // if
10681
10682   // copy source to result -- this will effectively truncate the left operand to the size of result!
10683   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10684   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10685   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10686     pic16_mov2f (AOP(result),AOP(left), offset);
10687   } // for
10688
10689   // if result is longer than left, fill with zeros (or sign)
10690   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10691     if (sign && AOP_SIZE(left) > 0) {
10692       // shift signed operand -- fill with sign
10693       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10694       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10695       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10696       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10697         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10698       } // for
10699     } else {
10700       // shift unsigned operand -- fill result with zeros
10701       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10702         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10703       } // for
10704     }
10705   } // if (size mismatch)
10706
10707   pic16_mov2w (AOP(right), 0);
10708   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10709   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10710   
10711 #if 0
10712   // perform a shift by one (shift count is positive)
10713   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10714   // 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])
10715   pic16_emitpLabel (label_loop_pos->key);
10716   emitCLRC;
10717   if (sign && (pos_shift == POC_RRCF)) {
10718     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10719     emitSETC;
10720   } // if
10721   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10722   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10723   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10724 #else
10725   // perform a shift by one (shift count is positive)
10726   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10727   // 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])
10728   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10729   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10730   emitCLRC;
10731   pic16_emitpLabel (label_loop_pos->key);
10732   if (sign && (pos_shift == POC_RRCF)) {
10733     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10734     emitSETC;
10735   } // if
10736   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10737   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10738   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10739   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10740 #endif
10741
10742   if (signedCount) {
10743     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10744
10745     pic16_emitpLabel (label_negative->key);
10746     // perform a shift by -1 (shift count is negative)
10747     // 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)
10748     emitCLRC;
10749     pic16_emitpLabel (label_loop_neg->key);
10750     if (sign && (neg_shift == POC_RRCF)) {
10751       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10752       emitSETC;
10753     } // if
10754     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10755     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10756     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10757     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10758   } // if (signedCount)
10759
10760   pic16_emitpLabel (label_complete->key);
10761
10762 release:
10763   pic16_freeAsmop (right,NULL,ic,TRUE);
10764   pic16_freeAsmop(left,NULL,ic,TRUE);
10765   pic16_freeAsmop(result,NULL,ic,TRUE);
10766 }
10767
10768 static void genLeftShift (iCode *ic) {
10769   genGenericShift (ic, 1);
10770 }
10771
10772 static void genRightShift (iCode *ic) {
10773   genGenericShift (ic, 0);
10774 }
10775 #endif
10776
10777
10778 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10779 void pic16_loadFSR0(operand *op, int lit)
10780 {
10781   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10782     if (AOP_TYPE(op) == AOP_LIT) {
10783       /* handle 12 bit integers correctly */
10784       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10785       if ((val & 0x0fff) != val) {
10786         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10787                 val, (val & 0x0fff) );
10788         val &= 0x0fff;
10789       }
10790       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10791     } else {
10792       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10793     }
10794   } else {
10795     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10796     // set up FSR0 with address of result
10797     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10798     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10799   }
10800 }
10801
10802 /*----------------------------------------------------------------*/
10803 /* pic16_derefPtr - move one byte from the location ptr points to */
10804 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10805 /*                  to the location ptr points to (doWrite != 0)   */
10806 /*----------------------------------------------------------------*/
10807 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10808 {
10809   if (!IS_PTR(operandType(ptr)))
10810   {
10811     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10812     else pic16_mov2w (AOP(ptr), 0);
10813     return;
10814   }
10815
10816   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10817   /* We might determine pointer type right here: */
10818   p_type = DCL_TYPE(operandType(ptr));
10819
10820   switch (p_type) {
10821     case FPOINTER:
10822     case POINTER:
10823       if (!fsr0_setup || !*fsr0_setup)
10824       {
10825         pic16_loadFSR0( ptr, 0 );
10826         if (fsr0_setup) *fsr0_setup = 1;
10827       }
10828       if (doWrite)
10829         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10830       else
10831         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10832       break;
10833
10834     case GPOINTER:
10835       if (AOP(ptr)->aopu.aop_reg[2]) {
10836         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10837         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10838         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10839         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10840         pic16_mov2w(AOP(ptr), 2);
10841         pic16_callGenericPointerRW(doWrite, 1);
10842       } else {
10843         // data pointer (just 2 byte given)
10844         if (!fsr0_setup || !*fsr0_setup)
10845         {
10846           pic16_loadFSR0( ptr, 0 );
10847           if (fsr0_setup) *fsr0_setup = 1;
10848         }
10849         if (doWrite)
10850           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10851         else
10852           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10853       }
10854       break;
10855
10856     default:
10857       assert (0 && "invalid pointer type specified");
10858       break;
10859   }
10860 }
10861
10862 /*-----------------------------------------------------------------*/
10863 /* genUnpackBits - generates code for unpacking bits               */
10864 /*-----------------------------------------------------------------*/
10865 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10866 {    
10867   int shCnt ;
10868   sym_link *etype, *letype;
10869   int blen=0, bstr=0;
10870   int lbstr;
10871   int same;
10872   pCodeOp *op;
10873
10874   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10875   etype = getSpec(operandType(result));
10876   letype = getSpec(operandType(left));
10877
10878   //    if(IS_BITFIELD(etype)) {
10879   blen = SPEC_BLEN(etype);
10880   bstr = SPEC_BSTR(etype);
10881   //    }
10882
10883   lbstr = SPEC_BSTR( letype );
10884
10885   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10886       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10887
10888 #if 1
10889   if((blen == 1) && (bstr < 8)
10890       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10891     /* it is a single bit, so use the appropriate bit instructions */
10892     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10893
10894     same = pic16_sameRegs(AOP(left),AOP(result));
10895     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10896     pic16_emitpcode(POC_CLRF, op);
10897
10898     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10899       /* workaround to reduce the extra lfsr instruction */
10900       pic16_emitpcode(POC_BTFSC,
10901           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10902     } else {
10903       assert (PIC_IS_DATA_PTR (operandType(left)));
10904       pic16_loadFSR0 (left, 0);
10905       pic16_emitpcode(POC_BTFSC,
10906           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10907     }
10908
10909     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10910       /* unsigned bitfields result in either 0 or 1 */
10911       pic16_emitpcode(POC_INCF, op);
10912     } else {
10913       /* signed bitfields result in either 0 or -1 */
10914       pic16_emitpcode(POC_DECF, op);
10915     }
10916     if (same) {
10917       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10918     }
10919
10920     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10921     return;
10922   }
10923
10924 #endif
10925
10926   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10927     // access symbol directly
10928     pic16_mov2w (AOP(left), 0);
10929   } else {
10930     pic16_derefPtr (left, ptype, 0, NULL);
10931   }
10932
10933   /* if we have bitdisplacement then it fits   */
10934   /* into this byte completely or if length is */
10935   /* less than a byte                          */
10936   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10937
10938     /* shift right acc */
10939     AccRsh(shCnt, 0);
10940
10941     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10942           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10943
10944     /* VR -- normally I would use the following, but since we use the hack,
10945      * to avoid the masking from AccRsh, why not mask it right now? */
10946
10947     /*
10948        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10949      */
10950
10951     /* extend signed bitfields to 8 bits */
10952     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10953     {
10954       assert (blen + bstr > 0);
10955       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10956       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10957     }
10958
10959     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10960
10961     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10962     return ;
10963   }
10964
10965   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10966   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10967   exit(EXIT_FAILURE);
10968
10969   return ;
10970 }
10971
10972
10973 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10974 {
10975   int size, offset = 0, leoffset=0 ;
10976
10977         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10978         pic16_aopOp(result, ic, TRUE);
10979
10980         FENTRY;
10981
10982         size = AOP_SIZE(result);
10983 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10984
10985
10986 #if 1
10987         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10988                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10989                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10990                 goto release;
10991         }
10992 #endif
10993
10994         if(AOP(left)->aopu.pcop->type == PO_DIR)
10995                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10996
10997         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10998
10999         while (size--) {
11000                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11001                 
11002 //              pic16_DumpOp("(result)",result);
11003                 if(is_LitAOp(AOP(result))) {
11004                         pic16_mov2w(AOP(left), offset); // patch 8
11005                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11006                 } else {
11007                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11008                                 pic16_popGet(AOP(left), offset), //patch 8
11009                                 pic16_popGet(AOP(result), offset)));
11010                 }
11011
11012                 offset++;
11013                 leoffset++;
11014         }
11015
11016 release:
11017     pic16_freeAsmop(result,NULL,ic,TRUE);
11018 }
11019
11020
11021
11022 /*-----------------------------------------------------------------*/
11023 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11024 /*-----------------------------------------------------------------*/
11025 static void genNearPointerGet (operand *left, 
11026                                operand *result, 
11027                                iCode *ic)
11028 {
11029 //  asmop *aop = NULL;
11030   //regs *preg = NULL ;
11031   sym_link *rtype, *retype;
11032   sym_link *ltype, *letype;
11033
11034     FENTRY;
11035     
11036     rtype = operandType(result);
11037     retype= getSpec(rtype);
11038     ltype = operandType(left);
11039     letype= getSpec(ltype);
11040     
11041     pic16_aopOp(left,ic,FALSE);
11042
11043 //    pic16_DumpOp("(left)",left);
11044 //    pic16_DumpOp("(result)",result);
11045
11046     /* if left is rematerialisable and
11047      * result is not bit variable type and
11048      * the left is pointer to data space i.e
11049      * lower 128 bytes of space */
11050     
11051     if (AOP_TYPE(left) == AOP_PCODE
11052       && !IS_BITFIELD(retype)
11053       && DCL_TYPE(ltype) == POINTER) {
11054
11055         genDataPointerGet (left,result,ic);
11056         pic16_freeAsmop(left, NULL, ic, TRUE);
11057         return ;
11058     }
11059     
11060     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11061     pic16_aopOp (result,ic,TRUE);
11062     
11063     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11064
11065 #if 1
11066     if(IS_BITFIELD( retype )
11067       && (SPEC_BLEN(operandType(result))==1)
11068     ) {
11069       iCode *nextic;
11070       pCodeOp *jop;
11071       int bitstrt, bytestrt;
11072
11073         /* if this is bitfield of size 1, see if we are checking the value
11074          * of a single bit in an if-statement,
11075          * if yes, then don't generate usual code, but execute the
11076          * genIfx directly -- VR */
11077
11078         nextic = ic->next;
11079
11080         /* CHECK: if next iCode is IFX
11081          * and current result operand is nextic's conditional operand
11082          * and current result operand live ranges ends at nextic's key number
11083          */
11084         if((nextic->op == IFX)
11085           && (result == IC_COND(nextic))
11086           && (OP_LIVETO(result) == nextic->seq)
11087           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11088           ) {
11089             /* everything is ok then */
11090             /* find a way to optimize the genIfx iCode */
11091
11092             bytestrt = SPEC_BSTR(operandType(result))/8;
11093             bitstrt = SPEC_BSTR(operandType(result))%8;
11094             
11095             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11096
11097             genIfxpCOpJump(nextic, jop);
11098             
11099             pic16_freeAsmop(left, NULL, ic, TRUE);
11100             pic16_freeAsmop(result, NULL, ic, TRUE);
11101             return;
11102         }
11103     }
11104 #endif
11105
11106     /* if bitfield then unpack the bits */
11107     if (IS_BITFIELD(letype)) 
11108       genUnpackBits (result, left, NULL, POINTER);
11109     else {
11110       /* we have can just get the values */
11111       int size = AOP_SIZE(result);
11112       int offset = 0;   
11113         
11114       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11115
11116       pic16_loadFSR0( left, 0 );
11117
11118       while(size--) {
11119         if(size) {
11120           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11121                 pic16_popGet(AOP(result), offset++)));
11122         } else {
11123           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11124                 pic16_popGet(AOP(result), offset++)));
11125         }
11126       }
11127     }
11128
11129 #if 0
11130     /* now some housekeeping stuff */
11131     if (aop) {
11132       /* we had to allocate for this iCode */
11133       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11134       pic16_freeAsmop(NULL,aop,ic,TRUE);
11135     } else { 
11136       /* we did not allocate which means left
11137        * already in a pointer register, then
11138        * if size > 0 && this could be used again
11139        * we have to point it back to where it 
11140        * belongs */
11141       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11142       if (AOP_SIZE(result) > 1
11143         && !OP_SYMBOL(left)->remat
11144         && ( OP_SYMBOL(left)->liveTo > ic->seq
11145             || ic->depth )) {
11146 //        int size = AOP_SIZE(result) - 1;
11147 //        while (size--)
11148 //          pic16_emitcode("dec","%s",rname);
11149         }
11150     }
11151 #endif
11152
11153     /* done */
11154     pic16_freeAsmop(left,NULL,ic,TRUE);
11155     pic16_freeAsmop(result,NULL,ic,TRUE);
11156 }
11157
11158 /*-----------------------------------------------------------------*/
11159 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11160 /*-----------------------------------------------------------------*/
11161 static void genPagedPointerGet (operand *left, 
11162                                operand *result, 
11163                                iCode *ic)
11164 {
11165     asmop *aop = NULL;
11166     regs *preg = NULL ;
11167     char *rname ;
11168     sym_link *rtype, *retype;    
11169
11170     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11171
11172     rtype = operandType(result);
11173     retype= getSpec(rtype);
11174     
11175     pic16_aopOp(left,ic,FALSE);
11176
11177   /* if the value is already in a pointer register
11178        then don't need anything more */
11179     if (!AOP_INPREG(AOP(left))) {
11180         /* otherwise get a free pointer register */
11181         aop = newAsmop(0);
11182         preg = getFreePtr(ic,&aop,FALSE);
11183         pic16_emitcode("mov","%s,%s",
11184                 preg->name,
11185                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11186         rname = preg->name ;
11187     } else
11188         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11189     
11190     pic16_freeAsmop(left,NULL,ic,TRUE);
11191     pic16_aopOp (result,ic,TRUE);
11192
11193     /* if bitfield then unpack the bits */
11194     if (IS_BITFIELD(retype)) 
11195         genUnpackBits (result,left,rname,PPOINTER);
11196     else {
11197         /* we have can just get the values */
11198         int size = AOP_SIZE(result);
11199         int offset = 0 ;        
11200         
11201         while (size--) {
11202             
11203             pic16_emitcode("movx","a,@%s",rname);
11204             pic16_aopPut(AOP(result),"a",offset);
11205             
11206             offset++ ;
11207             
11208             if (size)
11209                 pic16_emitcode("inc","%s",rname);
11210         }
11211     }
11212
11213     /* now some housekeeping stuff */
11214     if (aop) {
11215         /* we had to allocate for this iCode */
11216         pic16_freeAsmop(NULL,aop,ic,TRUE);
11217     } else { 
11218         /* we did not allocate which means left
11219            already in a pointer register, then
11220            if size > 0 && this could be used again
11221            we have to point it back to where it 
11222            belongs */
11223         if (AOP_SIZE(result) > 1 &&
11224             !OP_SYMBOL(left)->remat &&
11225             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11226               ic->depth )) {
11227             int size = AOP_SIZE(result) - 1;
11228             while (size--)
11229                 pic16_emitcode("dec","%s",rname);
11230         }
11231     }
11232
11233     /* done */
11234     pic16_freeAsmop(result,NULL,ic,TRUE);
11235     
11236         
11237 }
11238
11239 #if 0
11240 /* This code is not adjusted to PIC16 and fails utterly.
11241  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11242
11243 /*-----------------------------------------------------------------*/
11244 /* genFarPointerGet - gget value from far space                    */
11245 /*-----------------------------------------------------------------*/
11246 static void genFarPointerGet (operand *left,
11247                               operand *result, iCode *ic)
11248 {
11249     int size, offset ;
11250     sym_link *retype = getSpec(operandType(result));
11251
11252     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11253
11254     pic16_aopOp(left,ic,FALSE);
11255
11256     /* if the operand is already in dptr 
11257     then we do nothing else we move the value to dptr */
11258     if (AOP_TYPE(left) != AOP_STR) {
11259         /* if this is remateriazable */
11260         if (AOP_TYPE(left) == AOP_IMMD)
11261             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11262         else { /* we need to get it byte by byte */
11263             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11264             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11265             if (options.model == MODEL_FLAT24)
11266             {
11267                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11268             }
11269         }
11270     }
11271     /* so dptr know contains the address */
11272     pic16_freeAsmop(left,NULL,ic,TRUE);
11273     pic16_aopOp(result,ic,TRUE);
11274
11275     /* if bit then unpack */
11276     if (IS_BITFIELD(retype)) 
11277         genUnpackBits(result,left,"dptr",FPOINTER);
11278     else {
11279         size = AOP_SIZE(result);
11280         offset = 0 ;
11281
11282         while (size--) {
11283             pic16_emitcode("movx","a,@dptr");
11284             pic16_aopPut(AOP(result),"a",offset++);
11285             if (size)
11286                 pic16_emitcode("inc","dptr");
11287         }
11288     }
11289
11290     pic16_freeAsmop(result,NULL,ic,TRUE);
11291 }
11292 #endif
11293
11294 #if 0
11295 /*-----------------------------------------------------------------*/
11296 /* genCodePointerGet - get value from code space                  */
11297 /*-----------------------------------------------------------------*/
11298 static void genCodePointerGet (operand *left,
11299                                 operand *result, iCode *ic)
11300 {
11301     int size, offset ;
11302     sym_link *retype = getSpec(operandType(result));
11303
11304     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11305
11306     pic16_aopOp(left,ic,FALSE);
11307
11308     /* if the operand is already in dptr 
11309     then we do nothing else we move the value to dptr */
11310     if (AOP_TYPE(left) != AOP_STR) {
11311         /* if this is remateriazable */
11312         if (AOP_TYPE(left) == AOP_IMMD)
11313             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11314         else { /* we need to get it byte by byte */
11315             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11316             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11317             if (options.model == MODEL_FLAT24)
11318             {
11319                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11320             }
11321         }
11322     }
11323     /* so dptr know contains the address */
11324     pic16_freeAsmop(left,NULL,ic,TRUE);
11325     pic16_aopOp(result,ic,FALSE);
11326
11327     /* if bit then unpack */
11328     if (IS_BITFIELD(retype)) 
11329         genUnpackBits(result,left,"dptr",CPOINTER);
11330     else {
11331         size = AOP_SIZE(result);
11332         offset = 0 ;
11333
11334         while (size--) {
11335             pic16_emitcode("clr","a");
11336             pic16_emitcode("movc","a,@a+dptr");
11337             pic16_aopPut(AOP(result),"a",offset++);
11338             if (size)
11339                 pic16_emitcode("inc","dptr");
11340         }
11341     }
11342
11343     pic16_freeAsmop(result,NULL,ic,TRUE);
11344 }
11345 #endif
11346
11347 #if 0
11348 /*-----------------------------------------------------------------*/
11349 /* genGenPointerGet - gget value from generic pointer space        */
11350 /*-----------------------------------------------------------------*/
11351 static void genGenPointerGet (operand *left,
11352                               operand *result, iCode *ic)
11353 {
11354   int size, offset, lit;
11355   sym_link *retype = getSpec(operandType(result));
11356
11357         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11358         pic16_aopOp(left,ic,FALSE);
11359         pic16_aopOp(result,ic,FALSE);
11360         size = AOP_SIZE(result);
11361
11362         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11363
11364         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11365
11366                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11367                 // load FSR0 from immediate
11368                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11369
11370 //              pic16_loadFSR0( left );
11371
11372                 offset = 0;
11373                 while(size--) {
11374                         if(size) {
11375                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11376                         } else {
11377                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11378                         }
11379                         offset++;
11380                 }
11381                 goto release;
11382
11383         }
11384         else { /* we need to get it byte by byte */
11385                 // set up FSR0 with address from left
11386                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11387                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11388                 
11389                 offset = 0 ;
11390
11391                 while(size--) {
11392                         if(size) {
11393                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11394                         } else {
11395                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11396                         }
11397                         offset++;
11398                 }
11399                 goto release;
11400         }
11401
11402   /* if bit then unpack */
11403         if (IS_BITFIELD(retype)) 
11404                 genUnpackBits(result,left,"BAD",GPOINTER);
11405
11406         release:
11407         pic16_freeAsmop(left,NULL,ic,TRUE);
11408         pic16_freeAsmop(result,NULL,ic,TRUE);
11409
11410 }
11411 #endif
11412
11413
11414 /*-----------------------------------------------------------------*/
11415 /* genGenPointerGet - gget value from generic pointer space        */
11416 /*-----------------------------------------------------------------*/
11417 static void genGenPointerGet (operand *left,
11418                               operand *result, iCode *ic)
11419 {
11420   int size, offset, lit;
11421   sym_link *letype = getSpec(operandType(left));
11422
11423     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11424     pic16_aopOp(left,ic,FALSE);
11425     pic16_aopOp(result,ic,TRUE);
11426     size = AOP_SIZE(result);
11427
11428     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11429   
11430     /* if bit then unpack */
11431     if (IS_BITFIELD(letype)) {
11432       genUnpackBits(result,left,"BAD",GPOINTER);
11433       goto release;
11434     }
11435
11436     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11437
11438       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11439       // load FSR0 from immediate
11440       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11441
11442       werror(W_POSSBUG2, __FILE__, __LINE__);
11443
11444       offset = 0;
11445       while(size--) {
11446         if(size) {
11447           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11448         } else {
11449           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11450         }
11451         offset++;
11452       }
11453
11454       goto release;
11455
11456     } else { /* we need to get it byte by byte */
11457
11458       /* set up WREG:PRODL:FSR0L with address from left */
11459       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11460       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11461       pic16_mov2w(AOP(left), 2);
11462       pic16_callGenericPointerRW(0, size);
11463       
11464       assignResultValue(result, size, 1);
11465       
11466       goto release;
11467     }
11468
11469 release:
11470   pic16_freeAsmop(left,NULL,ic,TRUE);
11471   pic16_freeAsmop(result,NULL,ic,TRUE);
11472 }
11473
11474 /*-----------------------------------------------------------------*/
11475 /* genConstPointerGet - get value from const generic pointer space */
11476 /*-----------------------------------------------------------------*/
11477 static void genConstPointerGet (operand *left,
11478                                 operand *result, iCode *ic)
11479 {
11480   //sym_link *retype = getSpec(operandType(result));
11481   // symbol *albl = newiTempLabel(NULL);        // patch 15
11482   // symbol *blbl = newiTempLabel(NULL);        //
11483   // PIC_OPCODE poc;                            // patch 15
11484   int size;
11485   int offset = 0;
11486
11487   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11488   pic16_aopOp(left,ic,FALSE);
11489   pic16_aopOp(result,ic,TRUE);
11490   size = AOP_SIZE(result);
11491
11492   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11493
11494   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11495
11496   // set up table pointer
11497   if( (AOP_TYPE(left) == AOP_PCODE) 
11498       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11499           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11500     {
11501       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11502       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11503       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11504       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11505       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11506       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11507   } else {
11508     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11509     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11510     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11511   }
11512
11513   while(size--) {
11514     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11515     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11516     offset++;
11517   }
11518     
11519   pic16_freeAsmop(left,NULL,ic,TRUE);
11520   pic16_freeAsmop(result,NULL,ic,TRUE);
11521 }
11522
11523
11524 /*-----------------------------------------------------------------*/
11525 /* genPointerGet - generate code for pointer get                   */
11526 /*-----------------------------------------------------------------*/
11527 static void genPointerGet (iCode *ic)
11528 {
11529   operand *left, *result ;
11530   sym_link *type, *etype;
11531   int p_type;
11532
11533     FENTRY;
11534     
11535     left = IC_LEFT(ic);
11536     result = IC_RESULT(ic) ;
11537
11538     /* depending on the type of pointer we need to
11539     move it to the correct pointer register */
11540     type = operandType(left);
11541     etype = getSpec(type);
11542
11543 #if 0
11544     if (IS_PTR_CONST(type))
11545 #else
11546     if (IS_CODEPTR(type))
11547 #endif
11548       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11549
11550     /* if left is of type of pointer then it is simple */
11551     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11552       p_type = DCL_TYPE(type);
11553     else {
11554       /* we have to go by the storage class */
11555       p_type = PTR_TYPE(SPEC_OCLS(etype));
11556
11557       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11558
11559       if (SPEC_OCLS(etype)->codesp ) {
11560         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11561         //p_type = CPOINTER ;   
11562       } else
11563       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11564         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11565         /*p_type = FPOINTER ;*/ 
11566       } else
11567       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11568         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11569         /* p_type = PPOINTER; */
11570       } else
11571       if (SPEC_OCLS(etype) == idata ) {
11572         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11573         /* p_type = IPOINTER; */
11574       } else {
11575         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11576         /* p_type = POINTER ; */
11577       }
11578     }
11579
11580     /* now that we have the pointer type we assign
11581     the pointer values */
11582     switch (p_type) {
11583       case POINTER:     
11584       case FPOINTER:
11585       case IPOINTER:
11586         genNearPointerGet (left,result,ic);
11587         break;
11588
11589       case PPOINTER:
11590         genPagedPointerGet(left,result,ic);
11591         break;
11592
11593 #if 0
11594       /* PICs do not support FAR pointers... */
11595       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11596       case FPOINTER:
11597         genFarPointerGet (left,result,ic);
11598         break;
11599 #endif
11600
11601       case CPOINTER:
11602         genConstPointerGet (left,result,ic);
11603         //pic16_emitcodePointerGet (left,result,ic);
11604         break;
11605
11606       case GPOINTER:
11607 #if 0
11608       if (IS_PTR_CONST(type))
11609         genConstPointerGet (left,result,ic);
11610       else
11611 #endif
11612         genGenPointerGet (left,result,ic);
11613       break;
11614
11615     default:
11616       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11617               "genPointerGet: illegal pointer type");
11618     
11619     }
11620 }
11621
11622 /*-----------------------------------------------------------------*/
11623 /* genPackBits - generates code for packed bit storage             */
11624 /*-----------------------------------------------------------------*/
11625 static void genPackBits (sym_link    *etype , operand *result,
11626                          operand *right ,
11627                          char *rname, int p_type)
11628 {
11629   int shCnt = 0 ;
11630   int offset = 0  ;
11631   int rLen = 0 ;
11632   int blen, bstr ;   
11633   int shifted_and_masked = 0;
11634   unsigned long lit = (unsigned long)-1;
11635   sym_link *retype;
11636
11637   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11638   blen = SPEC_BLEN(etype);
11639   bstr = SPEC_BSTR(etype);
11640
11641   retype = getSpec(operandType(right));
11642
11643   if(AOP_TYPE(right) == AOP_LIT) {
11644     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11645     
11646     if((blen == 1) && (bstr < 8)) {
11647       /* it is a single bit, so use the appropriate bit instructions */
11648
11649       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11650
11651       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11652         /* workaround to reduce the extra lfsr instruction */
11653         if(lit) {
11654           pic16_emitpcode(POC_BSF,
11655               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11656         } else {
11657           pic16_emitpcode(POC_BCF,
11658               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11659         }
11660       } else {
11661         if (PIC_IS_DATA_PTR(operandType(result))) {
11662           pic16_loadFSR0(result, 0);
11663           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11664               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11665         } else {
11666           /* get old value */
11667           pic16_derefPtr (result, p_type, 0, NULL);
11668           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11669               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11670           /* write back new value */
11671           pic16_derefPtr (result, p_type, 1, NULL);
11672         }
11673       }
11674
11675       return;
11676     }
11677     /* IORLW below is more efficient */
11678     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11679     lit = (lit & ((1UL << blen) - 1)) << bstr;
11680     shifted_and_masked = 1;
11681     offset++;
11682   } else
11683     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11684         && IS_BITFIELD(retype) 
11685         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11686         && (blen == 1)) {
11687       int rblen, rbstr;
11688
11689       rblen = SPEC_BLEN( retype );
11690       rbstr = SPEC_BSTR( retype );
11691
11692       if(IS_BITFIELD(etype)) {
11693         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11694         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11695       } else {
11696         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11697       }
11698
11699       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11700
11701       if(IS_BITFIELD(etype)) {
11702         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11703       } else {
11704         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11705       }
11706
11707       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11708
11709       return;
11710     } else {
11711       /* move right to W */
11712       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11713     }
11714
11715   /* if the bit length is less than or   */
11716   /* it exactly fits a byte then         */
11717   if((shCnt=SPEC_BSTR(etype))
11718       || SPEC_BLEN(etype) <= 8 )  {
11719     int fsr0_setup = 0;
11720
11721     if (blen != 8 || bstr != 0) {
11722       // we need to combine the value with the old value
11723       if(!shifted_and_masked)
11724       {
11725         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11726
11727         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11728             SPEC_BSTR(etype), SPEC_BLEN(etype));
11729
11730         /* shift left acc, do NOT mask the result again */
11731         AccLsh(shCnt, 0);
11732
11733         /* using PRODH as a temporary register here */
11734         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11735       }
11736
11737       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11738         || IS_DIRECT(result)) {
11739         /* access symbol directly */
11740         pic16_mov2w (AOP(result), 0);
11741       } else {
11742         /* get old value */
11743         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11744       }
11745 #if 1
11746       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11747             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11748                             (unsigned char)(0xff >> (8-bstr))) ));
11749       if (!shifted_and_masked) {
11750         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11751       } else {
11752         /* We have the shifted and masked (literal) right value in `lit' */
11753         if (lit != 0)
11754           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11755       }
11756     } // if (blen != 8 || bstr != 0)
11757
11758     /* write new value back */
11759     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11760         || IS_DIRECT(result)) {
11761       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11762     } else {
11763       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11764     }
11765 #endif
11766
11767     return;
11768   }
11769
11770
11771 #if 0
11772   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11773   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11774   exit(EXIT_FAILURE);
11775 #endif
11776
11777
11778   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11779   rLen = SPEC_BLEN(etype)-8;
11780
11781   /* now generate for lengths greater than one byte */
11782   while (1) {
11783     rLen -= 8 ;
11784     if (rLen <= 0 ) {
11785       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11786       break ;
11787     }
11788
11789     switch (p_type) {
11790       case POINTER:
11791         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11792         break;
11793
11794         /*
11795            case FPOINTER:
11796            MOVA(l);
11797            pic16_emitcode("movx","@dptr,a");
11798            break;
11799
11800            case GPOINTER:
11801            MOVA(l);
11802            DEBUGpic16_emitcode(";lcall","__gptrput");
11803            break;  
11804          */
11805       default:
11806         assert(0);
11807     }   
11808
11809
11810     pic16_mov2w(AOP(right), offset++);
11811   }
11812
11813   /* last last was not complete */
11814   if (rLen)   {
11815     /* save the byte & read byte */
11816     switch (p_type) {
11817       case POINTER:
11818         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11819         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11820         break;
11821
11822         /*
11823            case FPOINTER:
11824            pic16_emitcode ("mov","b,a");
11825            pic16_emitcode("movx","a,@dptr");
11826            break;
11827
11828            case GPOINTER:
11829            pic16_emitcode ("push","b");
11830            pic16_emitcode ("push","acc");
11831            pic16_emitcode ("lcall","__gptrget");
11832            pic16_emitcode ("pop","b");
11833            break;
11834          */
11835       default:
11836         assert(0);
11837     }
11838     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11839     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11840     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11841     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11842     //        pic16_emitcode ("orl","a,b");
11843   }
11844
11845   //    if (p_type == GPOINTER)
11846   //        pic16_emitcode("pop","b");
11847
11848   switch (p_type) {
11849
11850     case POINTER:
11851       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11852       //        pic16_emitcode("mov","@%s,a",rname);
11853       break;
11854       /*
11855          case FPOINTER:
11856          pic16_emitcode("movx","@dptr,a");
11857          break;
11858
11859          case GPOINTER:
11860          DEBUGpic16_emitcode(";lcall","__gptrput");
11861          break;                 
11862        */
11863     default:
11864       assert(0);
11865   }
11866
11867   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11868 }
11869
11870 /*-----------------------------------------------------------------*/
11871 /* genDataPointerSet - remat pointer to data space                 */
11872 /*-----------------------------------------------------------------*/
11873 static void genDataPointerSet(operand *right,
11874                               operand *result,
11875                               iCode *ic)
11876 {
11877   int size, offset = 0, resoffset=0 ;
11878
11879     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11880     pic16_aopOp(right,ic,FALSE);
11881
11882     size = AOP_SIZE(right);
11883
11884 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11885
11886 #if 0
11887     if ( AOP_TYPE(result) == AOP_PCODE) {
11888       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11889               AOP(result)->aopu.pcop->name,
11890                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11891               PCOR(AOP(result)->aopu.pcop)->instance:
11892               PCOI(AOP(result)->aopu.pcop)->offset);
11893     }
11894 #endif
11895
11896     if(AOP(result)->aopu.pcop->type == PO_DIR)
11897       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11898
11899     while (size--) {
11900       if (AOP_TYPE(right) == AOP_LIT) {
11901         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11902         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11903       } else {
11904         pic16_mov2w(AOP(right), offset);
11905         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11906       }
11907       offset++;
11908       resoffset++;
11909     }
11910
11911     pic16_freeAsmop(right,NULL,ic,TRUE);
11912 }
11913
11914
11915
11916 /*-----------------------------------------------------------------*/
11917 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11918 /*-----------------------------------------------------------------*/
11919 static void genNearPointerSet (operand *right,
11920                                operand *result, 
11921                                iCode *ic)
11922 {
11923   asmop *aop = NULL;
11924   sym_link *retype;
11925   sym_link *ptype = operandType(result);
11926   sym_link *resetype;
11927     
11928     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11929     retype= getSpec(operandType(right));
11930     resetype = getSpec(operandType(result));
11931   
11932     pic16_aopOp(result,ic,FALSE);
11933     
11934     /* if the result is rematerializable &
11935      * in data space & not a bit variable */
11936         
11937     /* and result is not a bit variable */
11938     if (AOP_TYPE(result) == AOP_PCODE
11939 //      && AOP_TYPE(result) == AOP_IMMD
11940       && DCL_TYPE(ptype) == POINTER
11941       && !IS_BITFIELD(retype)
11942       && !IS_BITFIELD(resetype)) {
11943
11944         genDataPointerSet (right,result,ic);
11945         pic16_freeAsmop(result,NULL,ic,TRUE);
11946       return;
11947     }
11948
11949     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11950     pic16_aopOp(right,ic,FALSE);
11951     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11952
11953     /* if bitfield then unpack the bits */
11954     if (IS_BITFIELD(resetype)) {
11955       genPackBits (resetype, result, right, NULL, POINTER);
11956     } else {
11957       /* we have can just get the values */
11958       int size = AOP_SIZE(right);
11959       int offset = 0 ;    
11960
11961         pic16_loadFSR0(result, 0);
11962             
11963         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11964         while (size--) {
11965           if (AOP_TYPE(right) == AOP_LIT) {
11966             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11967             if (size) {
11968               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11969             } else {
11970               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11971             }
11972           } else { // no literal
11973             if(size) {
11974               pic16_emitpcode(POC_MOVFF,
11975                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11976                   pic16_popCopyReg(&pic16_pc_postinc0)));
11977             } else {
11978               pic16_emitpcode(POC_MOVFF,
11979                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11980                   pic16_popCopyReg(&pic16_pc_indf0)));
11981             }
11982           }
11983           
11984           offset++;
11985         }
11986     }
11987
11988     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11989     /* now some housekeeping stuff */
11990     if (aop) {
11991       /* we had to allocate for this iCode */
11992       pic16_freeAsmop(NULL,aop,ic,TRUE);
11993     } else { 
11994       /* we did not allocate which means left
11995        * already in a pointer register, then
11996        * if size > 0 && this could be used again
11997        * we have to point it back to where it 
11998        * belongs */
11999       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12000       if (AOP_SIZE(right) > 1
12001         && !OP_SYMBOL(result)->remat
12002         && ( OP_SYMBOL(result)->liveTo > ic->seq
12003         || ic->depth )) {
12004
12005           int size = AOP_SIZE(right) - 1;
12006
12007             while (size--)
12008               pic16_emitcode("decf","fsr0,f");
12009               //pic16_emitcode("dec","%s",rname);
12010       }
12011     }
12012
12013     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12014     /* done */
12015 //release:
12016     pic16_freeAsmop(right,NULL,ic,TRUE);
12017     pic16_freeAsmop(result,NULL,ic,TRUE);
12018 }
12019
12020 /*-----------------------------------------------------------------*/
12021 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12022 /*-----------------------------------------------------------------*/
12023 static void genPagedPointerSet (operand *right,
12024                                operand *result, 
12025                                iCode *ic)
12026 {
12027     asmop *aop = NULL;
12028     regs *preg = NULL ;
12029     char *rname , *l;
12030     sym_link *retype;
12031        
12032     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12033
12034     retype= getSpec(operandType(right));
12035     
12036     pic16_aopOp(result,ic,FALSE);
12037     
12038     /* if the value is already in a pointer register
12039        then don't need anything more */
12040     if (!AOP_INPREG(AOP(result))) {
12041         /* otherwise get a free pointer register */
12042         aop = newAsmop(0);
12043         preg = getFreePtr(ic,&aop,FALSE);
12044         pic16_emitcode("mov","%s,%s",
12045                 preg->name,
12046                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12047         rname = preg->name ;
12048     } else
12049         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12050     
12051     pic16_freeAsmop(result,NULL,ic,TRUE);
12052     pic16_aopOp (right,ic,FALSE);
12053
12054     /* if bitfield then unpack the bits */
12055     if (IS_BITFIELD(retype)) 
12056         genPackBits (retype,result,right,rname,PPOINTER);
12057     else {
12058         /* we have can just get the values */
12059         int size = AOP_SIZE(right);
12060         int offset = 0 ;        
12061         
12062         while (size--) {
12063             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12064             
12065             MOVA(l);
12066             pic16_emitcode("movx","@%s,a",rname);
12067
12068             if (size)
12069                 pic16_emitcode("inc","%s",rname);
12070
12071             offset++;
12072         }
12073     }
12074     
12075     /* now some housekeeping stuff */
12076     if (aop) {
12077         /* we had to allocate for this iCode */
12078         pic16_freeAsmop(NULL,aop,ic,TRUE);
12079     } else { 
12080         /* we did not allocate which means left
12081            already in a pointer register, then
12082            if size > 0 && this could be used again
12083            we have to point it back to where it 
12084            belongs */
12085         if (AOP_SIZE(right) > 1 &&
12086             !OP_SYMBOL(result)->remat &&
12087             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12088               ic->depth )) {
12089             int size = AOP_SIZE(right) - 1;
12090             while (size--)
12091                 pic16_emitcode("dec","%s",rname);
12092         }
12093     }
12094
12095     /* done */
12096     pic16_freeAsmop(right,NULL,ic,TRUE);
12097     
12098         
12099 }
12100
12101 #if 0
12102 /* This code is not adjusted to PIC16 and fails utterly...
12103  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12104
12105 /*-----------------------------------------------------------------*/
12106 /* genFarPointerSet - set value from far space                     */
12107 /*-----------------------------------------------------------------*/
12108 static void genFarPointerSet (operand *right,
12109                               operand *result, iCode *ic)
12110 {
12111     int size, offset ;
12112     sym_link *retype = getSpec(operandType(right));
12113
12114     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12115     pic16_aopOp(result,ic,FALSE);
12116
12117     /* if the operand is already in dptr 
12118     then we do nothing else we move the value to dptr */
12119     if (AOP_TYPE(result) != AOP_STR) {
12120         /* if this is remateriazable */
12121         if (AOP_TYPE(result) == AOP_IMMD)
12122             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12123         else { /* we need to get it byte by byte */
12124             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12125             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12126             if (options.model == MODEL_FLAT24)
12127             {
12128                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12129             }
12130         }
12131     }
12132     /* so dptr know contains the address */
12133     pic16_freeAsmop(result,NULL,ic,TRUE);
12134     pic16_aopOp(right,ic,FALSE);
12135
12136     /* if bit then unpack */
12137     if (IS_BITFIELD(retype)) 
12138         genPackBits(retype,result,right,"dptr",FPOINTER);
12139     else {
12140         size = AOP_SIZE(right);
12141         offset = 0 ;
12142
12143         while (size--) {
12144             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12145             MOVA(l);
12146             pic16_emitcode("movx","@dptr,a");
12147             if (size)
12148                 pic16_emitcode("inc","dptr");
12149         }
12150     }
12151
12152     pic16_freeAsmop(right,NULL,ic,TRUE);
12153 }
12154 #endif
12155
12156 /*-----------------------------------------------------------------*/
12157 /* genGenPointerSet - set value from generic pointer space         */
12158 /*-----------------------------------------------------------------*/
12159 #if 0
12160 static void genGenPointerSet (operand *right,
12161                               operand *result, iCode *ic)
12162 {
12163         int i, size, offset, lit;
12164         sym_link *retype = getSpec(operandType(right));
12165
12166         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12167
12168         pic16_aopOp(result,ic,FALSE);
12169         pic16_aopOp(right,ic,FALSE);
12170         size = AOP_SIZE(right);
12171         offset = 0;
12172
12173         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12174
12175         /* if the operand is already in dptr 
12176                 then we do nothing else we move the value to dptr */
12177         if (AOP_TYPE(result) != AOP_STR) {
12178                 /* if this is remateriazable */
12179                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12180                 // WARNING: anythig until "else" is untested!
12181                 if (AOP_TYPE(result) == AOP_IMMD) {
12182                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12183                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12184                         // load FSR0 from immediate
12185                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12186                         offset = 0;
12187                         while(size--) {
12188                                 if(size) {
12189                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12190                                 } else {
12191                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12192                                 }
12193                                 offset++;
12194                         }
12195                         goto release;
12196                 }
12197                 else { /* we need to get it byte by byte */
12198                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12199                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12200
12201                         // set up FSR0 with address of result
12202                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12203                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12204
12205                         /* hack hack! see if this the FSR. If so don't load W */
12206                         if(AOP_TYPE(right) != AOP_ACC) {
12207
12208                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12209
12210                                 if(AOP_TYPE(right) == AOP_LIT)
12211                                 {
12212                                         // copy literal
12213                                         // note: pic16_popGet handles sign extension
12214                                         for(i=0;i<size;i++) {
12215                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12216                                                 if(i < size-1)
12217                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12218                                                 else
12219                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12220                                         }
12221                                 } else {
12222                                         // copy regs
12223
12224                                         for(i=0;i<size;i++) {
12225                                                 if(i < size-1)
12226                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12227                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12228                                                 else
12229                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12230                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12231                                         }
12232                                 }
12233                                 goto release;
12234                         } 
12235                         // right = ACC
12236                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12237                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12238                         goto release;
12239         } // if (AOP_TYPE(result) != AOP_IMMD)
12240
12241         } // if (AOP_TYPE(result) != AOP_STR)
12242         /* so dptr know contains the address */
12243
12244
12245         /* if bit then unpack */
12246         if (IS_BITFIELD(retype)) 
12247                 genPackBits(retype,result,right,"dptr",GPOINTER);
12248         else {
12249                 size = AOP_SIZE(right);
12250                 offset = 0 ;
12251
12252                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12253
12254                 // set up FSR0 with address of result
12255                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12256                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12257         
12258                 while (size--) {
12259                         if (AOP_TYPE(right) == AOP_LIT) {
12260                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12261                                 if (size) {
12262                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12263                                 } else {
12264                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12265                                 }
12266                         } else { // no literal
12267                                 if(size) {
12268                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12269                                 } else {
12270                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12271                                 }
12272                         }
12273                         offset++;
12274                 }
12275         }
12276
12277         release:
12278         pic16_freeAsmop(right,NULL,ic,TRUE);
12279         pic16_freeAsmop(result,NULL,ic,TRUE);
12280 }
12281 #endif
12282
12283 static void genGenPointerSet (operand *right,
12284                               operand *result, iCode *ic)
12285 {
12286   int size;
12287   sym_link *retype = getSpec(operandType(result));
12288
12289     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12290
12291     pic16_aopOp(result,ic,FALSE);
12292     pic16_aopOp(right,ic,FALSE);
12293     size = AOP_SIZE(right);
12294
12295     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12296
12297
12298     /* if bit then unpack */
12299     if (IS_BITFIELD(retype)) {
12300 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12301       genPackBits(retype,result,right,"dptr",GPOINTER);
12302       goto release;
12303     }
12304
12305     size = AOP_SIZE(right);
12306
12307     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12308
12309
12310     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12311
12312     /* value of right+0 is placed on stack, which will be retrieved
12313      * by the support function thus restoring the stack. The important
12314      * thing is that there is no need to manually restore stack pointer
12315      * here */
12316     pushaop(AOP(right), 0);
12317 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12318     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12319     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12320     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12321     
12322     /* load address to write to in WREG:FSR0H:FSR0L */
12323     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12324                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12325     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12326                                 pic16_popCopyReg(&pic16_pc_prodl)));
12327     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12328     
12329     pic16_callGenericPointerRW(1, size);
12330
12331 release:
12332     pic16_freeAsmop(right,NULL,ic,TRUE);
12333     pic16_freeAsmop(result,NULL,ic,TRUE);
12334 }
12335
12336 /*-----------------------------------------------------------------*/
12337 /* genPointerSet - stores the value into a pointer location        */
12338 /*-----------------------------------------------------------------*/
12339 static void genPointerSet (iCode *ic)
12340 {    
12341   operand *right, *result ;
12342   sym_link *type, *etype;
12343   int p_type;
12344
12345     FENTRY;
12346
12347     right = IC_RIGHT(ic);
12348     result = IC_RESULT(ic) ;
12349
12350     /* depending on the type of pointer we need to
12351     move it to the correct pointer register */
12352     type = operandType(result);
12353     etype = getSpec(type);
12354     
12355     /* if left is of type of pointer then it is simple */
12356     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12357         p_type = DCL_TYPE(type);
12358     }
12359     else {
12360         /* we have to go by the storage class */
12361         p_type = PTR_TYPE(SPEC_OCLS(etype));
12362
12363 /*      if (SPEC_OCLS(etype)->codesp ) { */
12364 /*          p_type = CPOINTER ;  */
12365 /*      } */
12366 /*      else */
12367 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12368 /*              p_type = FPOINTER ; */
12369 /*          else */
12370 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12371 /*                  p_type = PPOINTER ; */
12372 /*              else */
12373 /*                  if (SPEC_OCLS(etype) == idata ) */
12374 /*                      p_type = IPOINTER ; */
12375 /*                  else */
12376 /*                      p_type = POINTER ; */
12377     }
12378
12379     /* now that we have the pointer type we assign
12380     the pointer values */
12381     switch (p_type) {
12382       case POINTER:
12383       case FPOINTER:
12384       case IPOINTER:
12385         genNearPointerSet (right,result,ic);
12386         break;
12387
12388       case PPOINTER:
12389         genPagedPointerSet (right,result,ic);
12390         break;
12391
12392 #if 0
12393       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12394       case FPOINTER:
12395         genFarPointerSet (right,result,ic);
12396         break;
12397 #endif
12398         
12399       case GPOINTER:
12400         genGenPointerSet (right,result,ic);
12401         break;
12402
12403       default:
12404         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12405           "genPointerSet: illegal pointer type");
12406     }
12407 }
12408
12409 /*-----------------------------------------------------------------*/
12410 /* genIfx - generate code for Ifx statement                        */
12411 /*-----------------------------------------------------------------*/
12412 static void genIfx (iCode *ic, iCode *popIc)
12413 {
12414   operand *cond = IC_COND(ic);
12415   int isbit =0;
12416
12417     FENTRY;
12418
12419     pic16_aopOp(cond,ic,FALSE);
12420
12421     /* get the value into acc */
12422     if (AOP_TYPE(cond) != AOP_CRY)
12423       pic16_toBoolean(cond);
12424     else
12425       isbit = 1;
12426     /* the result is now in the accumulator */
12427     pic16_freeAsmop(cond,NULL,ic,TRUE);
12428
12429     /* if there was something to be popped then do it */
12430     if (popIc)
12431       genIpop(popIc);
12432
12433     /* if the condition is  a bit variable */
12434     if (isbit && IS_ITEMP(cond) && 
12435         SPIL_LOC(cond)) {
12436       genIfxJump(ic,"c");
12437       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12438     } else {
12439       if (isbit && !IS_ITEMP(cond))
12440         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12441         else
12442         genIfxJump(ic,"a");
12443     }
12444     ic->generated = 1;
12445 }
12446
12447 /*-----------------------------------------------------------------*/
12448 /* genAddrOf - generates code for address of                       */
12449 /*-----------------------------------------------------------------*/
12450 static void genAddrOf (iCode *ic)
12451 {
12452   operand *result, *left;
12453   int size;
12454   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12455   pCodeOp *pcop0, *pcop1, *pcop2;
12456
12457     FENTRY;
12458
12459     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12460
12461     sym = OP_SYMBOL( IC_LEFT(ic) );
12462     
12463     if(sym->onStack) {
12464       /* get address of symbol on stack */
12465       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12466 #if 0
12467       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12468                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12469 #endif
12470
12471       // operands on stack are accessible via "FSR2 + index" with index
12472       // starting at 2 for arguments and growing from 0 downwards for
12473       // local variables (index == 0 is not assigned so we add one here)
12474       {
12475         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12476
12477           if (soffs <= 0) {
12478             assert (soffs < 0);
12479             soffs++;
12480           } // if
12481
12482           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12483           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12484           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12485           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12486           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12487           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12488           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12489       }
12490
12491       goto release;
12492     }
12493         
12494 //      if(pic16_debug_verbose) {
12495 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12496 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12497 //      }
12498         
12499     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12500     size = AOP_SIZE(IC_RESULT(ic));
12501
12502     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12503     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12504     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12505         
12506     if (size == 3) {
12507       pic16_emitpcode(POC_MOVLW, pcop0);
12508       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12509       pic16_emitpcode(POC_MOVLW, pcop1);
12510       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12511       pic16_emitpcode(POC_MOVLW, pcop2);
12512       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12513     } else
12514     if (size == 2) {
12515       pic16_emitpcode(POC_MOVLW, pcop0);
12516       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12517       pic16_emitpcode(POC_MOVLW, pcop1);
12518     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12519     } else {
12520       pic16_emitpcode(POC_MOVLW, pcop0);
12521       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12522     }
12523
12524     pic16_freeAsmop(left, NULL, ic, FALSE);
12525 release:
12526     pic16_freeAsmop(result,NULL,ic,TRUE);
12527 }
12528
12529
12530 #if 0
12531 /*-----------------------------------------------------------------*/
12532 /* genFarFarAssign - assignment when both are in far space         */
12533 /*-----------------------------------------------------------------*/
12534 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12535 {
12536     int size = AOP_SIZE(right);
12537     int offset = 0;
12538     char *l ;
12539     /* first push the right side on to the stack */
12540     while (size--) {
12541         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12542         MOVA(l);
12543         pic16_emitcode ("push","acc");
12544     }
12545     
12546     pic16_freeAsmop(right,NULL,ic,FALSE);
12547     /* now assign DPTR to result */
12548     pic16_aopOp(result,ic,FALSE);
12549     size = AOP_SIZE(result);
12550     while (size--) {
12551         pic16_emitcode ("pop","acc");
12552         pic16_aopPut(AOP(result),"a",--offset);
12553     }
12554     pic16_freeAsmop(result,NULL,ic,FALSE);
12555         
12556 }
12557 #endif
12558
12559 /*-----------------------------------------------------------------*/
12560 /* genAssign - generate code for assignment                        */
12561 /*-----------------------------------------------------------------*/
12562 static void genAssign (iCode *ic)
12563 {
12564   operand *result, *right;
12565   sym_link *restype, *rtype;
12566   int size, offset,know_W;
12567   unsigned long lit = 0L;
12568
12569     result = IC_RESULT(ic);
12570     right  = IC_RIGHT(ic) ;
12571
12572     FENTRY;
12573   
12574     /* if they are the same */
12575     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12576       return ;
12577
12578     /* reversed order operands are aopOp'ed so that result operand
12579      * is effective in case right is a stack symbol. This maneauver
12580      * allows to use the _G.resDirect flag later */
12581      pic16_aopOp(result,ic,TRUE);
12582     pic16_aopOp(right,ic,FALSE);
12583
12584     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12585
12586     /* if they are the same registers */
12587     if (pic16_sameRegs(AOP(right),AOP(result)))
12588       goto release;
12589
12590     /* if the result is a bit */
12591     if (AOP_TYPE(result) == AOP_CRY) {
12592       /* if the right size is a literal then
12593          we know what the value is */
12594       if (AOP_TYPE(right) == AOP_LIT) {
12595           
12596         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12597             pic16_popGet(AOP(result),0));
12598
12599         if (((int) operandLitValue(right))) 
12600           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12601               AOP(result)->aopu.aop_dir,
12602               AOP(result)->aopu.aop_dir);
12603         else
12604           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12605               AOP(result)->aopu.aop_dir,
12606               AOP(result)->aopu.aop_dir);
12607         
12608         goto release;
12609       }
12610
12611       /* the right is also a bit variable */
12612       if (AOP_TYPE(right) == AOP_CRY) {
12613         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12614         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12615         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12616
12617         goto release ;
12618       }
12619
12620       /* we need to or */
12621       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12622       pic16_toBoolean(right);
12623       emitSKPZ;
12624       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12625       //pic16_aopPut(AOP(result),"a",0);
12626       goto release ;
12627     }
12628
12629     /* bit variables done */
12630     /* general case */
12631     size = AOP_SIZE(result);
12632     offset = 0 ;
12633
12634   /* bit variables done */
12635   /* general case */
12636   size = AOP_SIZE(result);
12637   restype = operandType(result);
12638   rtype = operandType(right);
12639   offset = 0 ;
12640
12641   if(AOP_TYPE(right) == AOP_LIT) {
12642     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12643     {
12644       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12645
12646       /* patch tag for literals that are cast to pointers */
12647       if (IS_CODEPTR(restype)) {
12648         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12649         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12650       } else {
12651         if (IS_GENPTR(restype))
12652         {
12653           if (IS_CODEPTR(rtype)) {
12654             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12655             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12656           } else if (PIC_IS_DATA_PTR(rtype)) {
12657             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12658             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12659           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12660             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12661           } else if (IS_PTR(rtype)) {
12662             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12663             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12664           }
12665         }
12666       }
12667     } else {
12668       union {
12669         unsigned long lit_int;
12670         float lit_float;
12671       } info;
12672
12673
12674       if(IS_FIXED16X16(operandType(right))) {
12675         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12676       } else {
12677         /* take care if literal is a float */
12678         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12679         lit = info.lit_int;
12680       }
12681     }
12682   }
12683
12684 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12685 //                      sizeof(unsigned long int), sizeof(float));
12686
12687
12688     if (AOP_TYPE(right) == AOP_REG) {
12689       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12690       while (size--) {
12691         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12692       } // while
12693       goto release;
12694     }
12695
12696     /* when do we have to read the program memory?
12697      * - if right itself is a symbol in code space
12698      *   (we don't care what it points to if it's a pointer)
12699      * - AND right is not a function (we would want its address)
12700      */
12701     if(AOP_TYPE(right) != AOP_LIT
12702       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12703       && !IS_FUNC(OP_SYM_TYPE(right))
12704       && !IS_ITEMP(right)) {
12705
12706       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12707       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12708       
12709       // set up table pointer
12710       if(is_LitOp(right)) {
12711 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12712         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12713         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12714         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12715         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12716         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12717         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12718       } else {
12719 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12720         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12721             pic16_popCopyReg(&pic16_pc_tblptrl)));
12722         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12723             pic16_popCopyReg(&pic16_pc_tblptrh)));
12724         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12725             pic16_popCopyReg(&pic16_pc_tblptru)));
12726       }
12727
12728       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12729       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12730       while(size--) {
12731         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12732         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12733             pic16_popGet(AOP(result),offset)));
12734         offset++;
12735       }
12736
12737       /* FIXME: for pointers we need to extend differently (according
12738        * to pointer type DATA/CODE/EEPROM/... :*/
12739       size = getSize(OP_SYM_TYPE(right));
12740       if(AOP_SIZE(result) > size) {
12741         size = AOP_SIZE(result) - size;
12742         while(size--) {
12743           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12744           offset++;
12745         }
12746       }
12747       goto release;
12748     }
12749
12750 #if 0
12751     /* VR - What is this?! */
12752     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12753       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12754       
12755       if(aopIdx(AOP(result),0) == 4) {
12756         /* this is a workaround to save value of right into wreg too,
12757          * value of wreg is going to be used later */
12758         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12759         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12760         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12761         goto release;
12762       } else
12763 //      assert(0);
12764       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12765     }
12766 #endif
12767
12768     size = AOP_SIZE(right);
12769     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12770     know_W=-1;
12771     while (size--) {
12772       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12773       if(AOP_TYPE(right) == AOP_LIT) {
12774         if(lit&0xff) {
12775           if(know_W != (lit&0xff))
12776             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12777           know_W = lit&0xff;
12778           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12779         } else
12780           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12781
12782         lit >>= 8;
12783
12784       } else if (AOP_TYPE(right) == AOP_CRY) {
12785         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12786         if(offset == 0) {
12787           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12788           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12789           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12790         }
12791       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12792         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12793         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12794       } else {
12795         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12796
12797         if(!_G.resDirect) {                                             /* use this aopForSym feature */
12798           if(AOP_TYPE(result) == AOP_ACC) {
12799             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12800           } else
12801             if(AOP_TYPE(right) == AOP_ACC) {
12802               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12803             } else {
12804               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12805             }
12806         }
12807       }
12808
12809       offset++;
12810     }
12811     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12812   
12813 release:
12814   pic16_freeAsmop (right,NULL,ic,FALSE);
12815   pic16_freeAsmop (result,NULL,ic,TRUE);
12816
12817
12818 /*-----------------------------------------------------------------*/
12819 /* genJumpTab - generates code for jump table                       */
12820 /*-----------------------------------------------------------------*/
12821 static void genJumpTab (iCode *ic)
12822 {
12823   symbol *jtab;
12824   char *l;
12825   pCodeOp *jt_offs;
12826   pCodeOp *jt_offs_hi;
12827   pCodeOp *jt_label;
12828
12829     FENTRY;
12830
12831     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12832     /* get the condition into accumulator */
12833     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12834     MOVA(l);
12835     /* multiply by three */
12836     pic16_emitcode("add","a,acc");
12837     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12838
12839     jtab = newiTempLabel(NULL);
12840     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12841     pic16_emitcode("jmp","@a+dptr");
12842     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12843
12844 #if 0
12845     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12846     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12847     emitSKPNC;
12848     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12849     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12850     pic16_emitpLabel(jtab->key);
12851
12852 #else
12853
12854     jt_offs = pic16_popGetTempReg(0);
12855     jt_offs_hi = pic16_popGetTempReg(1);
12856     jt_label = pic16_popGetLabel (jtab->key);
12857     //fprintf (stderr, "Creating jump table...\n");
12858
12859     // calculate offset into jump table (idx * sizeof (GOTO))
12860     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12861     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12862     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12863     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12864     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12865     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12866     pic16_emitpcode(POC_MOVWF , jt_offs);
12867
12868     // prepare PCLATx (set to first entry in jump table)
12869     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12870     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12871     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12872     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12873     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12874
12875     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12876     pic16_emitpcode(POC_ADDWF , jt_offs);
12877     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12878     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12879     emitSKPNC;
12880     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12881
12882     // release temporaries and prepare jump into table (new PCL --> WREG)
12883     pic16_emitpcode(POC_MOVFW , jt_offs);
12884     pic16_popReleaseTempReg (jt_offs_hi, 1);
12885     pic16_popReleaseTempReg (jt_offs, 0);
12886
12887     // jump into the table
12888     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12889
12890     pic16_emitpLabelFORCE(jtab->key);
12891 #endif
12892
12893     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12894 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12895
12896     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12897     /* now generate the jump labels */
12898     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12899          jtab = setNextItem(IC_JTLABELS(ic))) {
12900 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12901         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12902         
12903     }
12904     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12905
12906 }
12907
12908 /*-----------------------------------------------------------------*/
12909 /* genMixedOperation - gen code for operators between mixed types  */
12910 /*-----------------------------------------------------------------*/
12911 /*
12912   TSD - Written for the PIC port - but this unfortunately is buggy.
12913   This routine is good in that it is able to efficiently promote 
12914   types to different (larger) sizes. Unfortunately, the temporary
12915   variables that are optimized out by this routine are sometimes
12916   used in other places. So until I know how to really parse the 
12917   iCode tree, I'm going to not be using this routine :(.
12918 */
12919 static int genMixedOperation (iCode *ic)
12920 {
12921 #if 0
12922   operand *result = IC_RESULT(ic);
12923   sym_link *ctype = operandType(IC_LEFT(ic));
12924   operand *right = IC_RIGHT(ic);
12925   int ret = 0;
12926   int big,small;
12927   int offset;
12928
12929   iCode *nextic;
12930   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12931
12932   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12933
12934   nextic = ic->next;
12935   if(!nextic)
12936     return 0;
12937
12938   nextright = IC_RIGHT(nextic);
12939   nextleft  = IC_LEFT(nextic);
12940   nextresult = IC_RESULT(nextic);
12941
12942   pic16_aopOp(right,ic,FALSE);
12943   pic16_aopOp(result,ic,FALSE);
12944   pic16_aopOp(nextright,  nextic, FALSE);
12945   pic16_aopOp(nextleft,   nextic, FALSE);
12946   pic16_aopOp(nextresult, nextic, FALSE);
12947
12948   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12949
12950     operand *t = right;
12951     right = nextright;
12952     nextright = t; 
12953
12954     pic16_emitcode(";remove right +","");
12955
12956   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12957 /*
12958     operand *t = right;
12959     right = nextleft;
12960     nextleft = t; 
12961 */
12962     pic16_emitcode(";remove left +","");
12963   } else
12964     return 0;
12965
12966   big = AOP_SIZE(nextleft);
12967   small = AOP_SIZE(nextright);
12968
12969   switch(nextic->op) {
12970
12971   case '+':
12972     pic16_emitcode(";optimize a +","");
12973     /* if unsigned or not an integral type */
12974     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12975       pic16_emitcode(";add a bit to something","");
12976     } else {
12977
12978       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12979
12980       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12981         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12982         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12983       } else
12984         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12985
12986       offset = 0;
12987       while(--big) {
12988
12989         offset++;
12990
12991         if(--small) {
12992           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12993             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12994             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12995           }
12996
12997           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12998           emitSKPNC;
12999           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13000                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13001                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13002           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13003           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13004
13005         } else {
13006           pic16_emitcode("rlf","known_zero,w");
13007
13008           /*
13009             if right is signed
13010               btfsc  right,7
13011                addlw ff
13012           */
13013           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13014             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13015             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13016           } else {
13017             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13018           }
13019         }
13020       }
13021       ret = 1;
13022     }
13023   }
13024   ret = 1;
13025
13026 release:
13027   pic16_freeAsmop(right,NULL,ic,TRUE);
13028   pic16_freeAsmop(result,NULL,ic,TRUE);
13029   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13030   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13031   if(ret)
13032     nextic->generated = 1;
13033
13034   return ret;
13035 #else
13036   return 0;
13037 #endif
13038 }
13039 /*-----------------------------------------------------------------*/
13040 /* genCast - gen code for casting                                  */
13041 /*-----------------------------------------------------------------*/
13042 static void genCast (iCode *ic)
13043 {
13044   operand *result = IC_RESULT(ic);
13045   sym_link *ctype = operandType(IC_LEFT(ic));
13046   sym_link *rtype = operandType(IC_RIGHT(ic));
13047   sym_link *restype = operandType(IC_RESULT(ic));
13048   operand *right = IC_RIGHT(ic);
13049   int size, offset ;
13050
13051
13052     FENTRY;
13053
13054         /* if they are equivalent then do nothing */
13055 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13056 //              return ;
13057
13058         pic16_aopOp(result,ic,FALSE);
13059         pic16_aopOp(right,ic,FALSE) ;
13060
13061         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13062
13063
13064         /* if the result is a bit */
13065         if (AOP_TYPE(result) == AOP_CRY) {
13066         
13067                 /* if the right size is a literal then
13068                  * we know what the value is */
13069                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13070
13071                 if (AOP_TYPE(right) == AOP_LIT) {
13072                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13073                                 pic16_popGet(AOP(result),0));
13074
13075                         if (((int) operandLitValue(right))) 
13076                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13077                                         AOP(result)->aopu.aop_dir,
13078                                         AOP(result)->aopu.aop_dir);
13079                         else
13080                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13081                                         AOP(result)->aopu.aop_dir,
13082                                         AOP(result)->aopu.aop_dir);
13083                         goto release;
13084                 }
13085
13086                 /* the right is also a bit variable */
13087                 if (AOP_TYPE(right) == AOP_CRY) {
13088                         emitCLRC;
13089                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13090
13091                         pic16_emitcode("clrc","");
13092                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13093                                 AOP(right)->aopu.aop_dir,
13094                                 AOP(right)->aopu.aop_dir);
13095                         pic16_aopPut(AOP(result),"c",0);
13096                         goto release ;
13097                 }
13098
13099                 /* we need to or */
13100                 if (AOP_TYPE(right) == AOP_REG) {
13101                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13102                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13103                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13104                 }
13105                 pic16_toBoolean(right);
13106                 pic16_aopPut(AOP(result),"a",0);
13107                 goto release ;
13108         }
13109
13110         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13111           int offset = 1;
13112
13113                 size = AOP_SIZE(result);
13114
13115                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13116
13117                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13118                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13119                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13120
13121                 while (size--)
13122                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13123
13124                 goto release;
13125         }
13126
13127         if(IS_BITFIELD(getSpec(restype))
13128           && IS_BITFIELD(getSpec(rtype))) {
13129           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13130         }
13131         
13132         /* port from pic14 to cope with generic pointers */
13133         if (PIC_IS_TAGGED(restype))
13134         {
13135           operand *result = IC_RESULT(ic);
13136           //operand *left = IC_LEFT(ic);
13137           operand *right = IC_RIGHT(ic);
13138           int tag = 0xff;
13139
13140           /* copy common part */
13141           int max, size = AOP_SIZE(result);
13142           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13143           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13144
13145           max = size;
13146           while (size--)
13147           {
13148             pic16_mov2w (AOP(right), size);
13149             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13150           } // while
13151
13152           /* upcast into generic pointer type? */
13153           if (IS_GENPTR(restype)
13154               && !PIC_IS_TAGGED(rtype)
13155               && (AOP_SIZE(result) > max))
13156           {
13157             /* determine appropriate tag for right */
13158             if (PIC_IS_DATA_PTR(rtype))
13159               tag = GPTR_TAG_DATA;
13160             else if (IS_CODEPTR(rtype))
13161               tag = GPTR_TAG_CODE;
13162             else if (PIC_IS_DATA_PTR(ctype)) {
13163               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13164               tag = GPTR_TAG_DATA;
13165             } else if (IS_CODEPTR(ctype)) {
13166               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13167               tag = GPTR_TAG_CODE;
13168             } else if (IS_PTR(rtype)) {
13169               PERFORM_ONCE(weirdcast,
13170               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13171               );
13172               tag = GPTR_TAG_DATA;
13173             } else {
13174               PERFORM_ONCE(weirdcast,
13175               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13176               );
13177               tag = GPTR_TAG_DATA;
13178             }
13179
13180             assert (AOP_SIZE(result) == 3);
13181             /* zero-extend address... */
13182             for (size = max; size < AOP_SIZE(result)-1; size++)
13183               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13184             /* ...and add tag */
13185             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13186           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13187             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13188             for (size = max; size < AOP_SIZE(result)-1; size++)
13189               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13190             /* add __code tag */
13191             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13192           } else if (AOP_SIZE(result) > max) {
13193             /* extend non-pointers */
13194             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13195             pic16_addSign(result, max, 0);
13196           } // if
13197           goto release;
13198         }
13199
13200         /* if they are the same size : or less */
13201         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13202
13203                 /* if they are in the same place */
13204                 if (pic16_sameRegs(AOP(right),AOP(result)))
13205                         goto release;
13206
13207                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13208 #if 0
13209                 if (IS_PTR_CONST(rtype))
13210 #else
13211                 if (IS_CODEPTR(rtype))
13212 #endif
13213                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13214
13215 #if 0
13216                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13217 #else
13218                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13219 #endif
13220                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13221
13222 #if 0
13223                 if(AOP_TYPE(right) == AOP_IMMD) {
13224                   pCodeOp *pcop0, *pcop1, *pcop2;
13225                   symbol *sym = OP_SYMBOL( right );
13226
13227                         size = AOP_SIZE(result);
13228                         /* low */
13229                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13230                         /* high */
13231                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13232                         /* upper */
13233                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13234         
13235                         if (size == 3) {
13236                                 pic16_emitpcode(POC_MOVLW, pcop0);
13237                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13238                                 pic16_emitpcode(POC_MOVLW, pcop1);
13239                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13240                                 pic16_emitpcode(POC_MOVLW, pcop2);
13241                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13242                         } else
13243                         if (size == 2) {
13244                                 pic16_emitpcode(POC_MOVLW, pcop0);
13245                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13246                                 pic16_emitpcode(POC_MOVLW, pcop1);
13247                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13248                         } else {
13249                                 pic16_emitpcode(POC_MOVLW, pcop0);
13250                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13251                         }
13252                 } else
13253 #endif
13254                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13255                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13256                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13257
13258                         if(AOP_SIZE(result) < 2) {
13259                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13260                         } else {
13261                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13262                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13263                         }
13264                 } else {
13265                         /* if they in different places then copy */
13266                         size = AOP_SIZE(result);
13267                         offset = 0 ;
13268                         while (size--) {
13269                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13270                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13271                                 offset++;
13272                         }
13273                 }
13274                 goto release;
13275         }
13276
13277         /* if the result is of type pointer */
13278         if (IS_PTR(ctype)) {
13279           int p_type;
13280           sym_link *type = operandType(right);
13281           sym_link *etype = getSpec(type);
13282
13283                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13284
13285                 /* pointer to generic pointer */
13286                 if (IS_GENPTR(ctype)) {
13287                   char *l = zero;
13288             
13289                         if (IS_PTR(type)) 
13290                                 p_type = DCL_TYPE(type);
13291                         else {
13292                 /* we have to go by the storage class */
13293                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13294
13295 /*              if (SPEC_OCLS(etype)->codesp )  */
13296 /*                  p_type = CPOINTER ;  */
13297 /*              else */
13298 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13299 /*                      p_type = FPOINTER ; */
13300 /*                  else */
13301 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13302 /*                          p_type = PPOINTER; */
13303 /*                      else */
13304 /*                          if (SPEC_OCLS(etype) == idata ) */
13305 /*                              p_type = IPOINTER ; */
13306 /*                          else */
13307 /*                              p_type = POINTER ; */
13308             }
13309                 
13310             /* the first two bytes are known */
13311       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13312             size = GPTRSIZE - 1; 
13313             offset = 0 ;
13314             while (size--) {
13315               if(offset < AOP_SIZE(right)) {
13316                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13317                 pic16_mov2f(AOP(result), AOP(right), offset);
13318 /*
13319                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13320                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13321                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13322                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13323                 } else { 
13324                   
13325                   pic16_aopPut(AOP(result),
13326                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13327                          offset);
13328                 }
13329 */
13330               } else 
13331                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13332               offset++;
13333             }
13334             /* the last byte depending on type */
13335             switch (p_type) {
13336             case IPOINTER:
13337             case POINTER:
13338             case FPOINTER:
13339                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13340                 break;
13341
13342             case CPOINTER:
13343                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13344                 break;
13345
13346             case PPOINTER:
13347               pic16_emitcode(";BUG!? ","%d",__LINE__);
13348                 l = "#0x03";
13349                 break;
13350
13351             case GPOINTER:
13352                 if (GPTRSIZE > AOP_SIZE(right)) {
13353                   // assume __data pointer... THIS MIGHT BE WRONG!
13354                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13355                 } else {
13356                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13357                 }
13358               break;
13359               
13360             default:
13361                 /* this should never happen */
13362                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13363                        "got unknown pointer type");
13364                 exit(1);
13365             }
13366             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13367             goto release ;
13368         }
13369         
13370         
13371         assert( 0 );
13372         /* just copy the pointers */
13373         size = AOP_SIZE(result);
13374         offset = 0 ;
13375         while (size--) {
13376             pic16_aopPut(AOP(result),
13377                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13378                    offset);
13379             offset++;
13380         }
13381         goto release ;
13382     }
13383     
13384
13385
13386     /* so we now know that the size of destination is greater
13387     than the size of the source.
13388     Now, if the next iCode is an operator then we might be
13389     able to optimize the operation without performing a cast.
13390     */
13391     if(genMixedOperation(ic))
13392       goto release;
13393
13394     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13395     
13396     /* we move to result for the size of source */
13397     size = AOP_SIZE(right);
13398     offset = 0 ;
13399
13400     while (size--) {
13401       if(!_G.resDirect)
13402         pic16_mov2f(AOP(result), AOP(right), offset);
13403       offset++;
13404     }
13405
13406     /* now depending on the sign of the destination */
13407     size = AOP_SIZE(result) - AOP_SIZE(right);
13408     /* if unsigned or not an integral type */
13409     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13410       while (size--)
13411         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13412     } else {
13413       /* we need to extend the sign :( */
13414
13415       if(size == 1) {
13416         /* Save one instruction of casting char to int */
13417         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13418         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13419         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13420       } else {
13421         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13422
13423         if(offset)
13424           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13425         else
13426           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13427         
13428         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13429
13430         while (size--)
13431           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13432       }
13433     }
13434
13435 release:
13436     pic16_freeAsmop(right,NULL,ic,TRUE);
13437     pic16_freeAsmop(result,NULL,ic,TRUE);
13438
13439 }
13440
13441 /*-----------------------------------------------------------------*/
13442 /* genDjnz - generate decrement & jump if not zero instrucion      */
13443 /*-----------------------------------------------------------------*/
13444 static int genDjnz (iCode *ic, iCode *ifx)
13445 {
13446     symbol *lbl, *lbl1;
13447     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13448
13449     if (!ifx)
13450         return 0;
13451     
13452     /* if the if condition has a false label
13453        then we cannot save */
13454     if (IC_FALSE(ifx))
13455         return 0;
13456
13457     /* if the minus is not of the form 
13458        a = a - 1 */
13459     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13460         !IS_OP_LITERAL(IC_RIGHT(ic)))
13461         return 0;
13462
13463     if (operandLitValue(IC_RIGHT(ic)) != 1)
13464         return 0;
13465
13466     /* if the size of this greater than one then no
13467        saving */
13468     if (getSize(operandType(IC_RESULT(ic))) > 1)
13469         return 0;
13470
13471     /* otherwise we can save BIG */
13472     lbl = newiTempLabel(NULL);
13473     lbl1= newiTempLabel(NULL);
13474
13475     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13476     
13477     if (IS_AOP_PREG(IC_RESULT(ic))) {
13478         pic16_emitcode("dec","%s",
13479                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13480         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13481         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13482     } else {    
13483
13484
13485       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13486       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13487
13488       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13489       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13490
13491     }
13492     
13493     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13494     ifx->generated = 1;
13495     return 1;
13496 }
13497
13498 /*-----------------------------------------------------------------*/
13499 /* genReceive - generate code for a receive iCode                  */
13500 /*-----------------------------------------------------------------*/
13501 static void genReceive (iCode *ic)
13502 {    
13503
13504   FENTRY;
13505
13506 #if 0
13507   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13508         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13509 #endif
13510 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13511
13512   if (isOperandInFarSpace(IC_RESULT(ic))
13513       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13514           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13515
13516     int size = getSize(operandType(IC_RESULT(ic)));
13517     int offset =  pic16_fReturnSizePic - size;
13518
13519       assert( 0 );
13520       while (size--) {
13521         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13522                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13523                       offset++;
13524         }
13525
13526       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13527
13528       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13529       size = AOP_SIZE(IC_RESULT(ic));
13530       offset = 0;
13531       while (size--) {
13532         pic16_emitcode ("pop","acc");
13533         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13534       }
13535   } else {
13536     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13537     _G.accInUse++;
13538     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13539     _G.accInUse--;
13540
13541     /* set pseudo stack pointer to where it should be - dw*/
13542     GpsuedoStkPtr = ic->parmBytes;
13543
13544     /* setting GpsuedoStkPtr has side effects here: */
13545     /* FIXME: What's the correct size of the return(ed) value?
13546      *        For now, assuming '4' as before... */
13547     assignResultValue(IC_RESULT(ic), 4, 0);
13548   }
13549
13550   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13551 }
13552
13553 /*-----------------------------------------------------------------*/
13554 /* genDummyRead - generate code for dummy read of volatiles        */
13555 /*-----------------------------------------------------------------*/
13556 static void
13557 genDummyRead (iCode * ic)
13558 {
13559   operand *op;
13560   int i;
13561
13562   op = IC_RIGHT(ic);
13563   if (op && IS_SYMOP(op)) {
13564     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13565       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13566       return;
13567     }
13568     pic16_aopOp (op, ic, FALSE);
13569     for (i=0; i < AOP_SIZE(op); i++) {
13570       // may need to protect this from the peepholer -- this is not nice but works...
13571       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13572       pic16_mov2w (AOP(op),i);
13573       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13574     } // for i
13575     pic16_freeAsmop (op, NULL, ic, TRUE);
13576   } else if (op) {
13577     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13578   } // if
13579 }
13580
13581 /*-----------------------------------------------------------------*/
13582 /* genpic16Code - generate code for pic16 based controllers        */
13583 /*-----------------------------------------------------------------*/
13584 /*
13585  * At this point, ralloc.c has gone through the iCode and attempted
13586  * to optimize in a way suitable for a PIC. Now we've got to generate
13587  * PIC instructions that correspond to the iCode.
13588  *
13589  * Once the instructions are generated, we'll pass through both the
13590  * peep hole optimizer and the pCode optimizer.
13591  *-----------------------------------------------------------------*/
13592
13593 void genpic16Code (iCode *lic)
13594 {
13595   iCode *ic;
13596   int cln = 0;
13597
13598     lineHead = lineCurr = NULL;
13599
13600     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13601     pic16_addpBlock(pb);
13602
13603 #if 0
13604     /* if debug information required */
13605     if (options.debug && currFunc) {
13606       if (currFunc) {
13607         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13608       }
13609     }
13610 #endif
13611
13612     for (ic = lic ; ic ; ic = ic->next ) {
13613
13614       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13615       if ( cln != ic->lineno ) {
13616         if ( options.debug ) {
13617           debugFile->writeCLine (ic);
13618         }
13619         
13620         if(!options.noCcodeInAsm) {
13621           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13622               printCLine(ic->filename, ic->lineno)));
13623         }
13624
13625         cln = ic->lineno ;
13626       }
13627         
13628       if(options.iCodeInAsm) {
13629         char *l;
13630
13631           /* insert here code to print iCode as comment */
13632           l = Safe_strdup(printILine(ic));
13633           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13634       }
13635
13636       /* if the result is marked as
13637        * spilt and rematerializable or code for
13638        * this has already been generated then
13639        * do nothing */
13640       if (resultRemat(ic) || ic->generated ) 
13641         continue ;
13642         
13643       /* depending on the operation */
13644       switch (ic->op) {
13645         case '!' :
13646           pic16_genNot(ic);
13647           break;
13648             
13649         case '~' :
13650           pic16_genCpl(ic);
13651           break;
13652             
13653         case UNARYMINUS:
13654           genUminus (ic);
13655           break;
13656             
13657         case IPUSH:
13658           genIpush (ic);
13659           break;
13660             
13661         case IPOP:
13662           /* IPOP happens only when trying to restore a 
13663            * spilt live range, if there is an ifx statement
13664            * following this pop then the if statement might
13665            * be using some of the registers being popped which
13666            * would destroy the contents of the register so
13667            * we need to check for this condition and handle it */
13668            if (ic->next
13669              && ic->next->op == IFX
13670              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13671                genIfx (ic->next,ic);
13672           else
13673             genIpop (ic);
13674           break; 
13675             
13676         case CALL:
13677           genCall (ic);
13678           break;
13679             
13680         case PCALL:
13681           genPcall (ic);
13682           break;
13683             
13684         case FUNCTION:
13685           genFunction (ic);
13686           break;
13687             
13688         case ENDFUNCTION:
13689           genEndFunction (ic);
13690           break;
13691             
13692         case RETURN:
13693           genRet (ic);
13694           break;
13695             
13696         case LABEL:
13697           genLabel (ic);
13698           break;
13699             
13700         case GOTO:
13701           genGoto (ic);
13702           break;
13703             
13704         case '+' :
13705           pic16_genPlus (ic) ;
13706           break;
13707             
13708         case '-' :
13709           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13710             pic16_genMinus (ic);
13711           break;
13712
13713         case '*' :
13714           genMult (ic);
13715           break;
13716             
13717         case '/' :
13718           genDiv (ic) ;
13719           break;
13720             
13721         case '%' :
13722           genMod (ic);
13723           break;
13724             
13725         case '>' :
13726           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13727           break;
13728             
13729         case '<' :
13730           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13731           break;
13732             
13733         case LE_OP:
13734         case GE_OP:
13735         case NE_OP:
13736           /* note these two are xlated by algebraic equivalence
13737            * during parsing SDCC.y */
13738           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13739             "got '>=' or '<=' shouldn't have come here");
13740           break;
13741
13742         case EQ_OP:
13743           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13744           break;            
13745             
13746         case AND_OP:
13747           genAndOp (ic);
13748           break;
13749             
13750         case OR_OP:
13751           genOrOp (ic);
13752           break;
13753             
13754         case '^' :
13755           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13756           break;
13757             
13758         case '|' :
13759           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13760           break;
13761             
13762         case BITWISEAND:
13763           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13764           break;
13765             
13766         case INLINEASM:
13767           genInline (ic);
13768           break;
13769             
13770         case RRC:
13771           genRRC (ic);
13772           break;
13773             
13774         case RLC:
13775           genRLC (ic);
13776           break;
13777             
13778         case GETHBIT:
13779           genGetHbit (ic);
13780           break;
13781             
13782         case LEFT_OP:
13783           genLeftShift (ic);
13784           break;
13785             
13786         case RIGHT_OP:
13787           genRightShift (ic);
13788           break;
13789             
13790         case GET_VALUE_AT_ADDRESS:
13791           genPointerGet(ic);
13792           break;
13793             
13794         case '=' :
13795           if (POINTER_SET(ic))
13796             genPointerSet(ic);
13797           else
13798             genAssign(ic);
13799           break;
13800             
13801         case IFX:
13802           genIfx (ic,NULL);
13803           break;
13804             
13805         case ADDRESS_OF:
13806           genAddrOf (ic);
13807           break;
13808             
13809         case JUMPTABLE:
13810           genJumpTab (ic);
13811           break;
13812             
13813         case CAST:
13814           genCast (ic);
13815           break;
13816             
13817         case RECEIVE:
13818           genReceive(ic);
13819           break;
13820             
13821         case SEND:
13822           addSet(&_G.sendSet,ic);
13823           break;
13824
13825         case DUMMY_READ_VOLATILE:
13826           genDummyRead (ic);
13827           break;
13828
13829         default :
13830           ic = ic;
13831       }
13832     }
13833
13834
13835     /* now we are ready to call the
13836        peep hole optimizer */
13837     if (!options.nopeep)
13838       peepHole (&lineHead);
13839
13840     /* now do the actual printing */
13841     printLine (lineHead, codeOutFile);
13842
13843 #ifdef PCODE_DEBUG
13844     DFPRINTF((stderr,"printing pBlock\n\n"));
13845     pic16_printpBlock(stdout,pb);
13846 #endif
13847
13848     return;
13849 }
13850