012f409d11d8e7c9a83cf3bd1132d294e766220c
[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 struct dbuf_s *codeOutBuf;
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     lineCurr->isComment = 1;
270
271     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
272     va_end(ap);
273
274 //      fprintf(stderr, "%s\n", lb);
275 }
276
277 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
278 {
279     va_list ap;
280     char lb[INITIAL_INLINEASM];  
281     unsigned char *lbp = (unsigned char *)lb;
282
283     if(!pic16_debug_verbose)
284       return;
285
286     va_start(ap,fmt);   
287
288     if (inst && *inst) {
289         if (fmt && *fmt)
290             sprintf(lb,"%s\t",inst);
291         else
292             sprintf(lb,"%s",inst);
293         vsprintf(lb+(strlen(lb)),fmt,ap);
294     }  else
295         vsprintf(lb,fmt,ap);
296
297     while (isspace(*lbp)) lbp++;
298
299     if (lbp && *lbp) 
300         lineCurr = (lineCurr ?
301                     connectLine(lineCurr,newLineNode(lb)) :
302                     (lineHead = newLineNode(lb)));
303     lineCurr->isInline = _G.inLine;
304     lineCurr->isDebug  = _G.debugLine;
305
306     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
307     va_end(ap);
308
309 //      fprintf(stderr, "%s\n", lb);
310 }
311
312
313
314 void pic16_emitpLabel(int key)
315 {
316   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
317 }
318
319 void pic16_emitpLabelFORCE(int key)
320 {
321   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
322 }
323
324 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
325  * NEVER call pic16_emitpcode_real directly, please... */
326 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
327 {
328
329   if(pcop)
330     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
331   else
332     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
333 }
334
335 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
336 {
337   if(pcop)
338     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
339   else
340     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
341 }
342   
343 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
344 {
345
346   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
347
348 }
349
350
351 #if 1
352 #define pic16_emitcode  DEBUGpic16_emitcode
353 #else
354 /*-----------------------------------------------------------------*/
355 /* pic16_emitcode - writes the code into a file : for now it is simple    */
356 /*-----------------------------------------------------------------*/
357 void pic16_emitcode (char *inst,char *fmt, ...)
358 {
359     va_list ap;
360     char lb[INITIAL_INLINEASM];  
361     unsigned char *lbp = lb;
362
363     va_start(ap,fmt);   
364
365     if (inst && *inst) {
366         if (fmt && *fmt)
367             sprintf(lb,"%s\t",inst);
368         else
369             sprintf(lb,"%s",inst);
370         vsprintf(lb+(strlen(lb)),fmt,ap);
371     }  else
372         vsprintf(lb,fmt,ap);
373
374     while (isspace(*lbp)) lbp++;
375
376     if (lbp && *lbp) 
377         lineCurr = (lineCurr ?
378                     connectLine(lineCurr,newLineNode(lb)) :
379                     (lineHead = newLineNode(lb)));
380     lineCurr->isInline = _G.inLine;
381     lineCurr->isDebug  = _G.debugLine;
382     lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
383     lineCurr->isComment = (*lbp == ';');
384
385 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
386
387 //    if(pic16_debug_verbose)
388 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
389
390     va_end(ap);
391 }
392 #endif
393
394
395 /*-----------------------------------------------------------------*/
396 /* pic16_emitDebuggerSymbol - associate the current code location  */
397 /*   with a debugger symbol                                        */
398 /*-----------------------------------------------------------------*/
399 void
400 pic16_emitDebuggerSymbol (char * debugSym)
401 {
402   _G.debugLine = 1;
403   pic16_emitcode (";", "%s ==.", debugSym);
404   _G.debugLine = 0;
405 }
406
407
408 /*-----------------------------------------------------------------*/
409 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
410 /*-----------------------------------------------------------------*/
411 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
412 {
413 //    bool r0iu = FALSE , r1iu = FALSE;
414 //    bool r0ou = FALSE , r1ou = FALSE;
415     bool fsr0iu = FALSE, fsr0ou;
416     bool fsr2iu = FALSE, fsr2ou;
417     
418     //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__,  __FUNCTION__, __LINE__, ic->op, result);
419
420     
421     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
422     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
423     
424     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
425     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
426
427     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
428         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
429         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
430     }
431
432     if(!fsr0iu && !fsr0ou) {
433         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
434         (*aopp)->type = AOP_FSR0;
435
436         //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
437         
438       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
439     }
440
441 #if 0
442     /* no usage of FSR2 */
443     if(!fsr2iu && !fsr2ou) {
444         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
445         (*aopp)->type = AOP_FSR2;
446
447       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
448     }
449 #endif
450         
451     /* now we know they both have usage */
452     /* if fsr0 not used in this instruction */
453     if (!fsr0iu) {
454         if (!_G.fsr0Pushed) {
455                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
456                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
457                 _G.fsr0Pushed++;
458         }
459
460         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
461         (*aopp)->type = AOP_FSR0;
462
463 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
464
465       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
466     }
467         
468
469     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
470     assert( 0 );
471
472     return NULL;
473 #if 0
474     /* the logic: if r0 & r1 used in the instruction
475     then we are in trouble otherwise */
476
477     /* first check if r0 & r1 are used by this
478     instruction, in which case we are in trouble */
479     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
480         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
481     {
482         goto endOfWorld;      
483     }
484
485     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
486     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
487
488     /* if no usage of r0 then return it */
489     if (!r0iu && !r0ou) {
490         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
491         (*aopp)->type = AOP_R0; 
492         
493         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
494     }
495
496     /* if no usage of r1 then return it */
497     if (!r1iu && !r1ou) {
498         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
499         (*aopp)->type = AOP_R1;
500
501         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
502     }    
503
504     /* now we know they both have usage */
505     /* if r0 not used in this instruction */
506     if (!r0iu) {
507         /* push it if not already pushed */
508         if (!_G.r0Pushed) {
509           //pic16_emitcode ("push","%s",
510           //          pic16_regWithIdx(R0_IDX)->dname);
511             _G.r0Pushed++ ;
512         }
513         
514         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
515         (*aopp)->type = AOP_R0;
516
517         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
518     }
519
520     /* if r1 not used then */
521
522     if (!r1iu) {
523         /* push it if not already pushed */
524         if (!_G.r1Pushed) {
525           //pic16_emitcode ("push","%s",
526           //          pic16_regWithIdx(R1_IDX)->dname);
527             _G.r1Pushed++ ;
528         }
529         
530         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
531         (*aopp)->type = AOP_R1;
532         return pic16_regWithIdx(R1_IDX);
533     }
534
535 endOfWorld :
536     /* I said end of world but not quite end of world yet */
537     /* if this is a result then we can push it on the stack*/
538     if (result) {
539         (*aopp)->type = AOP_STK;    
540         return NULL;
541     }
542
543     /* other wise this is true end of the world */
544     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
545            "getFreePtr should never reach here");
546     exit(0);
547 #endif
548 }
549
550 /*-----------------------------------------------------------------*/
551 /* newAsmop - creates a new asmOp                                  */
552 /*-----------------------------------------------------------------*/
553 static asmop *newAsmop (short type)
554 {
555     asmop *aop;
556
557     aop = Safe_calloc(1,sizeof(asmop));
558     aop->type = type;
559     return aop;
560 }
561
562 static void genSetDPTR(int n)
563 {
564     if (!n)
565     {
566         pic16_emitcode(";", "Select standard DPTR");
567         pic16_emitcode("mov", "dps, #0x00");
568     }
569     else
570     {
571         pic16_emitcode(";", "Select alternate DPTR");
572         pic16_emitcode("mov", "dps, #0x01");
573     }
574 }
575
576 /*-----------------------------------------------------------------*/
577 /* resolveIfx - converts an iCode ifx into a form more useful for  */
578 /*              generating code                                    */
579 /*-----------------------------------------------------------------*/
580 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
581 {
582   FENTRY2;
583   
584 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
585
586   if(!resIfx) 
587     return;
588
589
590   resIfx->condition = 1;    /* assume that the ifx is true */
591   resIfx->generated = 0;    /* indicate that the ifx has not been used */
592
593   if(!ifx) {
594     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
595
596 #if 1
597     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
598                         __FUNCTION__,__LINE__,resIfx->lbl->key);
599 #endif
600
601   } else {
602     if(IC_TRUE(ifx)) {
603       resIfx->lbl = IC_TRUE(ifx);
604     } else {
605       resIfx->lbl = IC_FALSE(ifx);
606       resIfx->condition = 0;
607     }
608
609 #if 1
610     if(IC_TRUE(ifx)) 
611       DEBUGpic16_emitcode("; +++","ifx true is non-null");
612     else
613       DEBUGpic16_emitcode("; +++","ifx true is null");
614     if(IC_FALSE(ifx)) 
615       DEBUGpic16_emitcode("; +++","ifx false is non-null");
616     else
617       DEBUGpic16_emitcode("; +++","ifx false is null");
618 #endif
619   }
620
621   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
622
623 }
624 #if 0
625 /*-----------------------------------------------------------------*/
626 /* pointerCode - returns the code for a pointer type               */
627 /*-----------------------------------------------------------------*/
628 static int pointerCode (sym_link *etype)
629 {
630
631     return PTR_TYPE(SPEC_OCLS(etype));
632
633 }
634 #endif
635
636 /*-----------------------------------------------------------------*/
637 /* aopForSym - for a true symbol                                   */
638 /*-----------------------------------------------------------------*/
639 static asmop *aopForSym (iCode *ic, operand *op, bool result)
640 {
641     symbol *sym=OP_SYMBOL(op);
642     asmop *aop;
643     memmap *space= SPEC_OCLS(sym->etype);
644
645     FENTRY2;
646     
647     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
648     
649 //    sym = OP_SYMBOL(op);
650
651     /* if already has one */
652     if (sym->aop) {
653             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
654         return sym->aop;
655     }
656
657 #if 0
658     /* if symbol was initially placed onStack then we must re-place it
659      * to direct memory, since pic16 does not have a specific stack */
660     if(sym->onStack) {
661         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
662     }
663 #endif
664
665
666 #if 0
667     if(sym->iaccess) {
668       if(space->paged) {
669         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
670
671         sym->aop = aop = newAsmop (AOP_PAGED);
672         aop->aopu.aop_dir = sym->rname ;
673         aop->size = getSize(sym->type);
674         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
675         pic16_allocDirReg( IC_LEFT(ic) );
676         return aop;
677       }
678       assert( 0 );
679     }
680 #endif
681     
682 #if 1
683     /* assign depending on the storage class */
684     /* if it is on the stack or indirectly addressable */
685     /* space we need to assign either r0 or r1 to it   */    
686     if (sym->onStack)   // || sym->iaccess)
687     {
688       pCodeOp *pcop[4];
689       int i;
690       
691         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
692                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
693         
694         /* acquire a temporary register -- it is saved in function */
695
696         sym->aop = aop = newAsmop(AOP_STA);
697         aop->aopu.stk.stk = sym->stack;
698         aop->size = getSize(sym->type);
699
700
701         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
702         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
703           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
704 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
705           
706           for(i=0;i<aop->size;i++)
707             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
708             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
709         } else
710         if(1 && ic->op == SEND) {
711
712           /* if SEND do the send here */
713           _G.resDirect = 1;
714         } else {
715 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
716           for(i=0;i<aop->size;i++) {
717             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
718             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
719           }
720         }
721
722
723 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
724
725 #if 1
726         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
727
728         // we do not need to load the value if it is to be defined...
729         if (result) return aop;
730
731         if(_G.accInUse) {
732                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
733         }
734         
735         for(i=0;i<aop->size;i++) {
736
737           /* initialise for stack access via frame pointer */
738           // operands on stack are accessible via "{FRAME POINTER} + index" with index
739           // starting at 2 for arguments and growing from 0 downwards for
740           // local variables (index == 0 is not assigned so we add one here)
741           {
742             int soffs = sym->stack;
743             if (soffs <= 0) {
744               assert (soffs < 0);
745               soffs++;
746             } // if
747
748             if(1 && ic->op == SEND) {
749               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
750               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
751                     pic16_popCopyReg( pic16_frame_plusw ),
752                     pic16_popCopyReg(pic16_stack_postdec )));
753             } else {
754               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
755               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
756                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
757             }
758           }
759         }
760         
761         if(_G.accInUse) {
762                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
763         }
764         
765         return (aop);
766 #endif
767
768 #if 0
769         /* now assign the address of the variable to 
770         the pointer register */
771         if (aop->type != AOP_STK) {
772
773             if (sym->onStack) {
774                     if ( _G.accInUse )
775                         pic16_emitcode("push","acc");
776
777                     pic16_emitcode("mov","a,_bp");
778                     pic16_emitcode("add","a,#0x%02x",
779                              ((sym->stack < 0) ?
780                               ((char)(sym->stack - _G.nRegsSaved )) :
781                               ((char)sym->stack)) & 0xff);
782                     pic16_emitcode("mov","%s,a",
783                              aop->aopu.aop_ptr->name);
784
785                     if ( _G.accInUse )
786                         pic16_emitcode("pop","acc");
787             } else
788                 pic16_emitcode("mov","%s,#%s",
789                          aop->aopu.aop_ptr->name,
790                          sym->rname);
791             aop->paged = space->paged;
792         } else
793             aop->aopu.aop_stk = sym->stack;
794         return aop;
795 #endif
796
797     }
798 #endif
799
800 #if 0
801     if (sym->onStack && options.stack10bit)
802     {
803         /* It's on the 10 bit stack, which is located in
804          * far data space.
805          */
806          
807       //DEBUGpic16_emitcode(";","%d",__LINE__);
808
809         if ( _G.accInUse )
810                 pic16_emitcode("push","acc");
811
812         pic16_emitcode("mov","a,_bp");
813         pic16_emitcode("add","a,#0x%02x",
814                  ((sym->stack < 0) ?
815                    ((char)(sym->stack - _G.nRegsSaved )) :
816                    ((char)sym->stack)) & 0xff);
817         
818         genSetDPTR(1);
819         pic16_emitcode ("mov","dpx1,#0x40");
820         pic16_emitcode ("mov","dph1,#0x00");
821         pic16_emitcode ("mov","dpl1, a");
822         genSetDPTR(0);
823         
824         if ( _G.accInUse )
825             pic16_emitcode("pop","acc");
826             
827         sym->aop = aop = newAsmop(AOP_DPTR2);
828         aop->size = getSize(sym->type); 
829         return aop;
830     }
831 #endif
832
833 #if 1
834     /* special case for a function */
835     if (IS_FUNC(sym->type)) {   
836         sym->aop = aop = newAsmop(AOP_PCODE);
837         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
838         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
839         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
840         PCOI(aop->aopu.pcop)->index = 0;
841         aop->size = FPTRSIZE; 
842         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
843         return aop;
844     }
845 #endif
846
847
848
849     //DEBUGpic16_emitcode(";","%d",__LINE__);
850     /* if in bit space */
851     if (IN_BITSPACE(space)) {
852         sym->aop = aop = newAsmop (AOP_CRY);
853         aop->aopu.aop_dir = sym->rname ;
854         aop->size = getSize(sym->type);
855         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
856         return aop;
857     }
858     /* if it is in direct space */
859     if (IN_DIRSPACE(space)) {
860                 if(!strcmp(sym->rname, "_WREG")) {
861                         sym->aop = aop = newAsmop (AOP_ACC);
862                         aop->size = getSize(sym->type);         /* should always be 1 */
863                         assert(aop->size == 1);
864                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
865                         return (aop);
866                 } else {
867                         sym->aop = aop = newAsmop (AOP_DIR);
868                 aop->aopu.aop_dir = sym->rname ;
869             aop->size = getSize(sym->type);
870                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
871                         pic16_allocDirReg( IC_LEFT(ic) );
872                         return (aop);
873                 }
874         }
875
876     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
877         sym->aop = aop = newAsmop (AOP_DIR);
878         aop->aopu.aop_dir = sym->rname ;
879         aop->size = getSize(sym->type);
880         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
881         pic16_allocDirReg( IC_LEFT(ic) );
882         return aop;
883     }
884
885
886     /* only remaining is far space */
887     sym->aop = aop = newAsmop(AOP_PCODE);
888
889 /* change the next if to 1 to revert to good old immediate code */
890         if(IN_CODESPACE(space)) {
891                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
892                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
893                 PCOI(aop->aopu.pcop)->index = 0;
894         } else {
895                 /* try to allocate via direct register */
896                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
897 //              aop->size = getSize( sym->type );
898         }
899
900         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
901                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
902
903 #if 0
904         if(!pic16_allocDirReg (IC_LEFT(ic)))
905                 return NULL;
906 #endif
907
908         if(IN_DIRSPACE( space ))
909                 aop->size = PTRSIZE;
910         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
911                 aop->size = FPTRSIZE;
912         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
913         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
914         else if(sym->onStack) {
915                 aop->size = PTRSIZE;
916         } else {
917           if(SPEC_SCLS(sym->etype) == S_PDATA) {
918             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
919             aop->size = FPTRSIZE;
920           } else
921                 assert( 0 );
922         }
923
924     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
925
926     /* if it is in code space */
927     if (IN_CODESPACE(space))
928         aop->code = 1;
929
930     return aop;     
931 }
932
933 /*-----------------------------------------------------------------*/
934 /* aopForRemat - rematerialzes an object                           */
935 /*-----------------------------------------------------------------*/
936 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
937 {
938   symbol *sym = OP_SYMBOL(op);
939   operand *refop;
940   iCode *ic = NULL, *oldic;
941   asmop *aop = newAsmop(AOP_PCODE);
942   int val = 0;
943   int offset = 0;
944   int viaimmd=0;
945
946     FENTRY2;
947     
948         ic = sym->rematiCode;
949
950         if(IS_OP_POINTER(op)) {
951                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
952         }
953
954 //    if(!result)               /* fixme-vr */
955         for (;;) {
956                 oldic = ic;
957
958 //              chat *iLine = printILine(ic);
959 //              pic16_emitpcomment("ic: %s\n", iLine);
960 //              dbuf_free(iLine);
961         
962                 if (ic->op == '+') {
963                         val += (int) operandLitValue(IC_RIGHT(ic));
964                 } else if (ic->op == '-') {
965                         val -= (int) operandLitValue(IC_RIGHT(ic));
966                 } else
967                         break;
968                 
969                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
970         }
971
972         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
973         refop = IC_LEFT(ic);
974
975         if(!op->isaddr)viaimmd++; else viaimmd=0;
976                 
977 /* set the following if to 1 to revert to good old immediate code */
978         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
979                 || viaimmd) {
980
981                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
982
983                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
984
985 #if 0
986                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
987 #else
988                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
989 #endif
990
991                 PCOI(aop->aopu.pcop)->index = val;
992                 
993                 aop->size = getSize( sym->type );
994         } else {
995                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
996
997                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
998                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
999
1000                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
1001         }
1002
1003
1004         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
1005                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
1006 #if 0
1007                 val, IS_PTR_CONST(operandType(op)));
1008 #else
1009                 val, IS_CODEPTR(operandType(op)));
1010 #endif
1011
1012 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1013
1014         pic16_allocDirReg (IC_LEFT(ic));
1015
1016         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1017                 aop->code = 1;
1018
1019   return aop;        
1020 }
1021
1022 #if 0
1023 static int aopIdx (asmop *aop, int offset)
1024 {
1025   if(!aop)
1026     return -1;
1027
1028   if(aop->type !=  AOP_REG)
1029     return -2;
1030         
1031   return aop->aopu.aop_reg[offset]->rIdx;
1032
1033 }
1034 #endif
1035
1036 /*-----------------------------------------------------------------*/
1037 /* regsInCommon - two operands have some registers in common       */
1038 /*-----------------------------------------------------------------*/
1039 static bool regsInCommon (operand *op1, operand *op2)
1040 {
1041     symbol *sym1, *sym2;
1042     int i;
1043
1044     /* if they have registers in common */
1045     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1046         return FALSE ;
1047
1048     sym1 = OP_SYMBOL(op1);
1049     sym2 = OP_SYMBOL(op2);
1050
1051     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1052         return FALSE ;
1053
1054     for (i = 0 ; i < sym1->nRegs ; i++) {
1055         int j;
1056         if (!sym1->regs[i])
1057             continue ;
1058
1059         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1060             if (!sym2->regs[j])
1061                 continue ;
1062
1063             if (sym2->regs[j] == sym1->regs[i])
1064                 return TRUE ;
1065         }
1066     }
1067
1068     return FALSE ;
1069 }
1070
1071 /*-----------------------------------------------------------------*/
1072 /* operandsEqu - equivalent                                        */
1073 /*-----------------------------------------------------------------*/
1074 static bool operandsEqu ( operand *op1, operand *op2)
1075 {
1076     symbol *sym1, *sym2;
1077
1078     /* if they not symbols */
1079     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1080         return FALSE;
1081
1082     sym1 = OP_SYMBOL(op1);
1083     sym2 = OP_SYMBOL(op2);
1084
1085     /* if both are itemps & one is spilt
1086        and the other is not then false */
1087     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1088         sym1->isspilt != sym2->isspilt )
1089         return FALSE ;
1090
1091     /* if they are the same */
1092     if (sym1 == sym2)
1093         return TRUE ;
1094
1095     if (sym1->rname[0] && sym2->rname[0]
1096         && strcmp (sym1->rname, sym2->rname) == 0)
1097         return TRUE;
1098
1099
1100     /* if left is a tmp & right is not */
1101     if (IS_ITEMP(op1)  && 
1102         !IS_ITEMP(op2) &&
1103         sym1->isspilt  &&
1104         (sym1->usl.spillLoc == sym2))
1105         return TRUE;
1106
1107     if (IS_ITEMP(op2)  && 
1108         !IS_ITEMP(op1) &&
1109         sym2->isspilt  &&
1110         sym1->level > 0 &&
1111         (sym2->usl.spillLoc == sym1))
1112         return TRUE ;
1113
1114     return FALSE ;
1115 }
1116
1117 /*-----------------------------------------------------------------*/
1118 /* pic16_sameRegs - two asmops have the same registers                   */
1119 /*-----------------------------------------------------------------*/
1120 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1121 {
1122     int i;
1123
1124     if (aop1 == aop2)
1125         return TRUE ;
1126
1127     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1128                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1129
1130     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1131
1132     if (aop1->type != AOP_REG ||
1133         aop2->type != AOP_REG )
1134         return FALSE ;
1135
1136     /* This is a bit too restrictive if one is a subset of the other...
1137     if (aop1->size != aop2->size )
1138         return FALSE ;
1139     */
1140
1141     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1142 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1143
1144 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1145         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1146             return FALSE ;
1147     }
1148
1149     return TRUE ;
1150 }
1151
1152 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1153 {
1154     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1155                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1156
1157     if(aop1 == aop2)return TRUE;
1158     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1159       
1160       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1161     
1162   return TRUE;
1163 }
1164
1165
1166 /*-----------------------------------------------------------------*/
1167 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1168 /*-----------------------------------------------------------------*/
1169 void pic16_aopOp (operand *op, iCode *ic, bool result)
1170 {
1171     asmop *aop;
1172     symbol *sym;
1173     int i;
1174
1175     if (!op)
1176         return ;
1177
1178     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1179
1180     /* if this a literal */
1181     if (IS_OP_LITERAL(op)) {
1182         op->aop = aop = newAsmop(AOP_LIT);
1183         aop->aopu.aop_lit = op->operand.valOperand;
1184         aop->size = getSize(operandType(op));
1185         return;
1186     }
1187
1188     {
1189       sym_link *type = operandType(op);
1190 #if 0
1191       if(IS_PTR_CONST(type))
1192 #else
1193       if(IS_CODEPTR(type))
1194 #endif
1195         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1196     }
1197
1198     /* if already has a asmop then continue */
1199     if (op->aop)
1200         return ;
1201
1202     /* if the underlying symbol has a aop */
1203     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1204       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1205         op->aop = OP_SYMBOL(op)->aop;
1206         return;
1207     }
1208
1209     /* if this is a true symbol */
1210     if (IS_TRUE_SYMOP(op)) {    
1211         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1212       op->aop = aopForSym(ic, op, result);
1213       return ;
1214     }
1215
1216     /* this is a temporary : this has
1217     only four choices :
1218     a) register
1219     b) spillocation
1220     c) rematerialize 
1221     d) conditional   
1222     e) can be a return use only */
1223
1224     sym = OP_SYMBOL(op);
1225
1226     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1227     /* if the type is a conditional */
1228     if (sym->regType == REG_CND) {
1229         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1230         aop->size = 0;
1231         return;
1232     }
1233
1234     /* if it is spilt then two situations
1235     a) is rematerialize 
1236     b) has a spill location */
1237     if (sym->isspilt || sym->nRegs == 0) {
1238
1239 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1240       DEBUGpic16_emitcode(";","%d",__LINE__);
1241         /* rematerialize it NOW */
1242         if (sym->remat) {
1243
1244             sym->aop = op->aop = aop = aopForRemat (op, result);
1245 //            aop->size = getSize(sym->type);
1246 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1247             return;
1248         }
1249
1250 #if 1
1251         if (sym->accuse) {
1252             int i;
1253             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1254             aop->size = getSize(sym->type);
1255             for ( i = 0 ; i < 1 ; i++ ) {
1256                 aop->aopu.aop_str[i] = accUse[i];
1257 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1258             }
1259             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1260             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1261             return;  
1262         }
1263 #endif
1264
1265 #if 1
1266         if (sym->ruonly) {
1267           /*
1268           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1269           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1270           //pic16_allocDirReg (IC_LEFT(ic));
1271           aop->size = getSize(sym->type);
1272           */
1273
1274           unsigned i;
1275
1276           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1277           aop->size = getSize(sym->type);
1278           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1279             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1280
1281           DEBUGpic16_emitcode(";","%d",__LINE__);
1282           return;
1283         }
1284 #endif
1285         /* else spill location  */
1286         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1287             /* force a new aop if sizes differ */
1288             sym->usl.spillLoc->aop = NULL;
1289         }
1290
1291 #if 0
1292         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1293                             __FUNCTION__,__LINE__,
1294                             sym->usl.spillLoc->rname,
1295                             sym->rname, sym->usl.spillLoc->offset);
1296 #endif
1297
1298         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1299         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1300           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1301           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1302                                                   getSize(sym->type), 
1303                                                   sym->usl.spillLoc->offset, op);
1304         } else if (getSize(sym->type) <= 1) {
1305           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1306           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1307           assert (getSize(sym->type) <= 1);
1308           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1309           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1310         } else {
1311           /* We need some kind of dummy area for getSize(sym->type) byte,
1312            * use WREG for all storage locations.
1313            * XXX: This only works if we are implementing a `dummy read',
1314            *      the stored value will not be retrievable...
1315            *      See #1503234 for a case requiring this. */
1316           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1317           aop->size = getSize(sym->type);
1318           for ( i = 0 ; i < aop->size ;i++)
1319             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1320         }
1321         aop->size = getSize(sym->type);
1322
1323         return;
1324     }
1325
1326     {
1327       sym_link *type = operandType(op);
1328 #if 0
1329       if(IS_PTR_CONST(type)) 
1330 #else
1331       if(IS_CODEPTR(type)) 
1332 #endif
1333         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1334     }
1335
1336     /* must be in a register */
1337     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1338     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1339     aop->size = sym->nRegs;
1340     for ( i = 0 ; i < sym->nRegs ;i++)
1341         aop->aopu.aop_reg[i] = sym->regs[i];
1342 }
1343
1344 /*-----------------------------------------------------------------*/
1345 /* pic16_freeAsmop - free up the asmop given to an operand               */
1346 /*----------------------------------------------------------------*/
1347 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1348 {   
1349     asmop *aop ;
1350
1351     if (!op)
1352         aop = aaop;
1353     else 
1354         aop = op->aop;
1355
1356     if (!aop)
1357         return ;
1358
1359     if (aop->freed)
1360         goto dealloc; 
1361
1362     aop->freed = 1;
1363
1364     /* depending on the asmop type only three cases need work AOP_RO
1365        , AOP_R1 && AOP_STK */
1366 #if 1
1367     switch (aop->type) {
1368         case AOP_FSR0 :
1369             if (_G.fsr0Pushed ) {
1370                 if (pop) {
1371                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1372                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1373 //                    pic16_emitcode ("pop","ar0");
1374                     _G.fsr0Pushed--;
1375                 }
1376             }
1377             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1378             break;
1379
1380         case AOP_FSR2 :
1381             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1382             break;
1383
1384         case AOP_R0 :
1385             if (_G.r0Pushed ) {
1386                 if (pop) {
1387                     pic16_emitcode ("pop","ar0");     
1388                     _G.r0Pushed--;
1389                 }
1390             }
1391             bitVectUnSetBit(ic->rUsed,R0_IDX);
1392             break;
1393
1394         case AOP_R1 :
1395             if (_G.r1Pushed ) {
1396                 if (pop) {
1397                     pic16_emitcode ("pop","ar1");
1398                     _G.r1Pushed--;
1399                 }
1400             }
1401             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1402             break;
1403
1404         case AOP_STA:
1405           {
1406             int i;
1407
1408               /* we must store the result on stack */
1409               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1410                 // operands on stack are accessible via "FSR2 + index" with index
1411                 // starting at 2 for arguments and growing from 0 downwards for
1412                 // local variables (index == 0 is not assigned so we add one here)
1413                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1414                 if (soffs <= 0) {
1415                   assert (soffs < 0);
1416                   soffs++;
1417                 } // if
1418                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1419                 for(i=0;i<aop->size;i++) {
1420                   /* initialise for stack access via frame pointer */
1421                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1422                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1423                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1424                 }
1425         
1426                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1427               }
1428
1429               if(!_G.resDirect) {
1430                 for(i=0;i<aop->size;i++) {
1431                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1432
1433                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1434                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1435 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1436                   }
1437                 }
1438                 
1439                 {
1440                   regs *sr;
1441                   
1442                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1443                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1444                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1445                       deleteSetItem( &_G.sregsAllocSet, sr );
1446                     }
1447                 }
1448               }
1449               _G.resDirect = 0;
1450           }
1451           break;
1452 #if 0
1453         case AOP_STK :
1454         {
1455             int sz = aop->size;    
1456             int stk = aop->aopu.aop_stk + aop->size;
1457             bitVectUnSetBit(ic->rUsed,R0_IDX);
1458             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1459
1460             getFreePtr(ic,&aop,FALSE);
1461             
1462             if (options.stack10bit)
1463             {
1464                 /* I'm not sure what to do here yet... */
1465                 /* #STUB */
1466                 fprintf(stderr, 
1467                         "*** Warning: probably generating bad code for "
1468                         "10 bit stack mode.\n");
1469             }
1470             
1471             if (stk) {
1472                 pic16_emitcode ("mov","a,_bp");
1473                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1474                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1475             } else {
1476                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1477             }
1478
1479             while (sz--) {
1480                 pic16_emitcode("pop","acc");
1481                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1482                 if (!sz) break;
1483                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1484             }
1485             op->aop = aop;
1486             pic16_freeAsmop(op,NULL,ic,TRUE);
1487             if (_G.r0Pushed) {
1488                 pic16_emitcode("pop","ar0");
1489                 _G.r0Pushed--;
1490             }
1491
1492             if (_G.r1Pushed) {
1493                 pic16_emitcode("pop","ar1");
1494                 _G.r1Pushed--;
1495             }       
1496         }
1497 #endif
1498
1499     }
1500 #endif
1501
1502 dealloc:
1503     /* all other cases just dealloc */
1504     if (op ) {
1505         op->aop = NULL;
1506         if (IS_SYMOP(op)) {
1507             OP_SYMBOL(op)->aop = NULL;    
1508             /* if the symbol has a spill */
1509             if (SPIL_LOC(op))
1510                 SPIL_LOC(op)->aop = NULL;
1511         }
1512     }
1513 }
1514
1515 /*-----------------------------------------------------------------*/
1516 /* pic16_aopGet - for fetching value of the aop                          */
1517 /*-----------------------------------------------------------------*/
1518 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1519 {
1520     char *s = buffer ;
1521     char *rs;
1522
1523     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1524
1525     /* offset is greater than size then zero */
1526     if (offset > (aop->size - 1) &&
1527         aop->type != AOP_LIT)
1528         return zero;
1529
1530     /* depending on type */
1531     switch (aop->type) {
1532
1533     case AOP_FSR0:
1534     case AOP_FSR2:
1535       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1536       rs = Safe_calloc(1, strlen(s)+1);
1537       strcpy(rs, s);
1538       return (rs);
1539       
1540 #if 0
1541       /* if we need to increment it */
1542       while (offset > aop->coff)
1543         {
1544           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1545           aop->coff++;
1546         }
1547
1548       while (offset < aop->coff)
1549         {
1550           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1551           aop->coff--;
1552         }
1553       aop->coff = offset;
1554       if (aop->paged)
1555         {
1556           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1557           return (dname ? "acc" : "a");
1558         }
1559       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1560       rs = Safe_calloc (1, strlen (s) + 1);
1561       strcpy (rs, s);
1562       return rs;
1563 #endif
1564
1565         
1566     case AOP_IMMD:
1567         if (bit16) 
1568             sprintf (s,"%s",aop->aopu.aop_immd);
1569         else
1570             if (offset) 
1571                 sprintf(s,"(%s >> %d)",
1572                         aop->aopu.aop_immd,
1573                         offset*8);
1574             else
1575                 sprintf(s,"%s",
1576                         aop->aopu.aop_immd);
1577         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1578         rs = Safe_calloc(1,strlen(s)+1);
1579         strcpy(rs,s);   
1580         return rs;
1581         
1582     case AOP_DIR:
1583       if (offset) {
1584         sprintf(s,"(%s + %d)",
1585                 aop->aopu.aop_dir,
1586                 offset);
1587         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1588       } else
1589             sprintf(s,"%s",aop->aopu.aop_dir);
1590         rs = Safe_calloc(1,strlen(s)+1);
1591         strcpy(rs,s);   
1592         return rs;
1593         
1594     case AOP_REG:
1595       return aop->aopu.aop_reg[offset]->name;
1596         
1597     case AOP_CRY:
1598       return aop->aopu.aop_dir;
1599         
1600     case AOP_ACC:
1601         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1602 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1603 //        assert( 0 );
1604 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1605         rs = Safe_strdup("WREG");
1606         return (rs);
1607
1608     case AOP_LIT:
1609         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1610         rs = Safe_calloc(1,strlen(s)+1);
1611         strcpy(rs,s);   
1612         return rs;
1613         
1614     case AOP_STR:
1615         aop->coff = offset ;
1616
1617 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1618 //          dname)
1619 //          return "acc";
1620         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1621           aop->type = AOP_ACC;
1622           return Safe_strdup("_WREG");
1623         }
1624         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1625         
1626         return aop->aopu.aop_str[offset];
1627         
1628     case AOP_PCODE:
1629       {
1630         pCodeOp *pcop = aop->aopu.pcop;
1631         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1632         if(pcop->name) {
1633           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1634           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1635           if (offset) {
1636             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1637           } else {
1638             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1639           }
1640         } else
1641           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1642
1643       }
1644       rs = Safe_calloc(1,strlen(s)+1);
1645       strcpy(rs,s);   
1646       return rs;
1647
1648 #if 0
1649     case AOP_PAGED:
1650       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1651       if (offset) {
1652         sprintf(s,"(%s + %d)",
1653                 aop->aopu.aop_dir,
1654                 offset);
1655       } else
1656             sprintf(s,"%s",aop->aopu.aop_dir);
1657       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1658       rs = Safe_calloc(1,strlen(s)+1);
1659       strcpy(rs,s);   
1660       return rs;
1661 #endif
1662
1663     case AOP_STA:
1664         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1665         return (rs);
1666         
1667     case AOP_STK:
1668 //        pCodeOp *pcop = aop->aop
1669         break;
1670
1671     }
1672
1673     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1674     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1675            "aopget got unsupported aop->type");
1676     exit(0);
1677 }
1678
1679
1680
1681 /* lock has the following meaning: When allocating temporary registers
1682  * for stack variables storage, the value of the temporary register is
1683  * saved on stack. Its value is restored at the end. This procedure is
1684  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1685  * a possibility that before a call to pic16_aopOp, a temporary register
1686  * is allocated for a while and it is freed after some time, this will
1687  * mess the stack and values will not be restored properly. So use lock=1
1688  * to allocate temporary registers used internally by the programmer, and
1689  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1690  * to inform the compiler developer about a possible bug. This is an internal
1691  * feature for developing the compiler -- VR */
1692  
1693 int _TempReg_lock = 0;
1694 /*-----------------------------------------------------------------*/
1695 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1696 /*-----------------------------------------------------------------*/
1697 pCodeOp *pic16_popGetTempReg(int lock)
1698 {
1699   pCodeOp *pcop=NULL;
1700   symbol *cfunc;
1701
1702 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1703     if(_TempReg_lock) {
1704 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1705     }
1706     
1707     _TempReg_lock += lock;
1708     
1709     cfunc = currFunc;
1710     currFunc = NULL;
1711
1712 #if 0
1713         {
1714           regs *rr;
1715           int i;
1716
1717                 /* this code might seem better but it does the *same* job with
1718                  * the old code, it all depends on ralloc.c to get a free/unused
1719                  * register */
1720          
1721                 i=0;
1722                 while(i < pic16_nRegs) {
1723                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1724                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1725                         if((!rr || (rr && rr->isFree))
1726                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1727                                 pcop = pic16_newpCodeOpReg( i );
1728                                 PCOR(pcop)->r->wasUsed = 1;
1729                                 PCOR(pcop)->r->isFree = 0;
1730                                 break;
1731                         }
1732                         i++;
1733                 }
1734
1735                 if(pcop) {
1736                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1737                 }
1738         }
1739 #else
1740     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1741     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1742       PCOR(pcop)->r->wasUsed=1;
1743       PCOR(pcop)->r->isFree=0;
1744
1745       /* push value on stack */
1746       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1747     }
1748 #endif
1749
1750     currFunc = cfunc;
1751
1752   return pcop;
1753 }
1754
1755 /*-----------------------------------------------------------------*/
1756 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1757 /*                           is not part of f, but don't save if   */
1758 /*                           inside v                              */
1759 /*-----------------------------------------------------------------*/
1760 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1761 {
1762   pCodeOp *pcop=NULL;
1763   symbol *cfunc;
1764   int i;
1765
1766 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1767
1768     if(_TempReg_lock) {
1769 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1770     }
1771
1772     _TempReg_lock += lock;
1773
1774     cfunc = currFunc;
1775     currFunc = NULL;
1776
1777     i = bitVectFirstBit(f);
1778     while(i < 128) {
1779
1780       /* bypass registers that are used by function */
1781       if(!bitVectBitValue(f, i)) {
1782       
1783         /* bypass registers that are already allocated for stack access */
1784         if(!bitVectBitValue(v, i))  {
1785         
1786 //          debugf("getting register rIdx = %d\n", i);
1787           /* ok, get the operand */
1788           pcop = pic16_newpCodeOpReg( i );
1789     
1790           /* should never by NULL */
1791           assert( pcop != NULL );
1792
1793           
1794           /* sanity check */
1795           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1796             int found=0;
1797             
1798               PCOR(pcop)->r->wasUsed=1;
1799               PCOR(pcop)->r->isFree=0;
1800
1801
1802               {
1803                 regs *sr;
1804               
1805                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1806
1807                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1808                       /* already used in previous steps, break */
1809                       found=1;          
1810                       break;
1811                     }
1812                   }
1813               }
1814
1815               /* caller takes care of the following */
1816 //              bitVectSetBit(v, i);
1817
1818               if(!found) {
1819                 /* push value on stack */
1820                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1821                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1822               }
1823           
1824             break;
1825           }
1826         }
1827       }
1828       i++;
1829     }
1830
1831     currFunc = cfunc;
1832
1833   return pcop;
1834 }
1835
1836
1837 /*-----------------------------------------------------------------*/
1838 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1839 /*-----------------------------------------------------------------*/
1840 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1841 {
1842   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1843
1844   _TempReg_lock -= lock;
1845
1846   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1847     PCOR(pcop)->r->isFree = 1;
1848
1849     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1850   }
1851 }
1852 /*-----------------------------------------------------------------*/
1853 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1854 /*-----------------------------------------------------------------*/
1855 pCodeOp *pic16_popGetLabel(int key)
1856 {
1857
1858   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1859
1860   if(key>max_key)
1861     max_key = key;
1862
1863   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1864 }
1865
1866 /*-----------------------------------------------------------------*/
1867 /* pic16_popCopyReg - copy a pcode operator                              */
1868 /*-----------------------------------------------------------------*/
1869 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1870 {
1871   pCodeOpReg *pcor;
1872
1873   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1874   memcpy (pcor, pc, sizeof (pCodeOpReg));
1875   pcor->r->wasUsed = 1;
1876   
1877   //pcor->pcop.type = pc->pcop.type;
1878   if(pc->pcop.name) {
1879     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1880       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1881   } else
1882     pcor->pcop.name = NULL;
1883
1884   //pcor->r = pc->r;
1885   //pcor->rIdx = pc->rIdx;
1886   //pcor->r->wasUsed=1;
1887   //pcor->instance = pc->instance;
1888
1889 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1890
1891   return PCOP(pcor);
1892 }
1893
1894 /*-----------------------------------------------------------------*/
1895 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1896 /*-----------------------------------------------------------------*/
1897 pCodeOp *pic16_popGetLit(int lit)
1898 {
1899   return pic16_newpCodeOpLit(lit);
1900 }
1901
1902 /* Allow for 12 bit literals (LFSR x, <here!>). */
1903 pCodeOp *pic16_popGetLit12(int lit)
1904 {
1905   return pic16_newpCodeOpLit12(lit);
1906 }
1907
1908 /*-----------------------------------------------------------------*/
1909 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1910 /*-----------------------------------------------------------------*/
1911 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1912 {
1913   return pic16_newpCodeOpLit2(lit, arg2);
1914 }
1915
1916
1917 /*-----------------------------------------------------------------*/
1918 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1919 /*-----------------------------------------------------------------*/
1920 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1921 {
1922   return pic16_newpCodeOpImmd(name, offset,index, 0);
1923 }
1924
1925
1926 /*-----------------------------------------------------------------*/
1927 /* pic16_popGet - asm operator to pcode operator conversion              */
1928 /*-----------------------------------------------------------------*/
1929 pCodeOp *pic16_popGetWithString(char *str)
1930 {
1931   pCodeOp *pcop;
1932
1933
1934   if(!str) {
1935     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1936     exit (1);
1937   }
1938
1939   pcop = pic16_newpCodeOp(str,PO_STR);
1940
1941   return pcop;
1942 }
1943
1944 /*-----------------------------------------------------------------*/
1945 /* pic16_popRegFromString -                                        */
1946 /*-----------------------------------------------------------------*/
1947 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1948 {
1949
1950   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1951   pcop->type = PO_DIR;
1952
1953   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1954   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1955
1956   if(!str)
1957     str = "BAD_STRING";
1958
1959   pcop->name = Safe_calloc(1,strlen(str)+1);
1960   strcpy(pcop->name,str);
1961
1962   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1963
1964   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1965 //  PCOR(pcop)->r->wasUsed = 1;
1966
1967   /* make sure that register doesn't exist,
1968    * and operand isn't NULL
1969    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1970   if((PCOR(pcop)->r == NULL) 
1971     && (op)
1972     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1973 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1974 //              __FUNCTION__, __LINE__, str, size, offset);
1975
1976     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1977     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1978
1979   }
1980   PCOR(pcop)->instance = offset;
1981
1982   return pcop;
1983 }
1984
1985 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1986 {
1987   pCodeOp *pcop;
1988
1989 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1990 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1991         
1992         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1993         PCOR(pcop)->rIdx = rIdx;
1994         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1995         if(!PCOR(pcop)->r)
1996                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1997                 
1998         PCOR(pcop)->r->isFree = 0;
1999         PCOR(pcop)->r->wasUsed = 1;
2000
2001         pcop->type = PCOR(pcop)->r->pc_type;
2002
2003   return pcop;
2004 }
2005
2006 /*---------------------------------------------------------------------------------*/
2007 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2008 /*                 VR 030601                                                       */
2009 /*---------------------------------------------------------------------------------*/
2010 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2011 {
2012   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2013         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2014   return PCOP(pcop2);
2015 }
2016
2017
2018
2019 /*--------------------------------------------------------------------------------.-*/
2020 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2021 /*                  VR 030601 , adapted by Hans Dorn                                */
2022 /*--------------------------------------------------------------------------------.-*/
2023 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2024 {
2025   pCodeOp2 *pcop2;
2026   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2027   return PCOP(pcop2);
2028 }
2029
2030 /*---------------------------------------------------------------------------------*/
2031 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2032 /*                     movff instruction                                           */
2033 /*---------------------------------------------------------------------------------*/
2034 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2035 {
2036   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2037         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2038
2039   return PCOP(pcop2);
2040 }
2041
2042
2043 /*-----------------------------------------------------------------*/
2044 /* pic16_popGet - asm operator to pcode operator conversion              */
2045 /*-----------------------------------------------------------------*/
2046 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2047 {
2048 //  char *s = buffer ;
2049 //  char *rs;
2050   pCodeOp *pcop;
2051
2052     FENTRY2;
2053     
2054       /* offset is greater than size then zero */
2055
2056 //    if (offset > (aop->size - 1) &&
2057 //        aop->type != AOP_LIT)
2058 //      return NULL;  //zero;
2059
2060     /* depending on type */
2061     switch (aop->type) {
2062                 case AOP_R0:
2063                 case AOP_R1:
2064                 case AOP_DPTR:
2065                 case AOP_DPTR2:
2066                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2067                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2068                         assert( 0 );
2069                         return NULL;
2070
2071                 case AOP_FSR0:
2072                 case AOP_FSR2:
2073                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2074                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2075                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2076                         PCOR(pcop)->r->wasUsed = 1;
2077                         PCOR(pcop)->r->isFree = 0;
2078       
2079                         PCOR(pcop)->instance = offset;
2080                         pcop->type = PCOR(pcop)->r->pc_type;
2081                         return (pcop);
2082
2083                 case AOP_IMMD:
2084                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2085                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2086
2087                 case AOP_STA:
2088                         /* pCodeOp is already allocated from aopForSym */
2089                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2090                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2091                         return (pcop);
2092       
2093                 case AOP_ACC:
2094                         {
2095                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2096
2097                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2098
2099                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2100         
2101                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2102                                 PCOR(pcop)->rIdx = rIdx;
2103                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2104                                 PCOR(pcop)->r->wasUsed=1;
2105                                 PCOR(pcop)->r->isFree=0;
2106
2107                                 PCOR(pcop)->instance = offset;
2108                                 pcop->type = PCOR(pcop)->r->pc_type;
2109 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2110                                 return pcop;
2111
2112
2113 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2114 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2115
2116 //      assert( 0 );
2117                         }
2118         
2119     case AOP_DIR:
2120       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2121       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2122         
2123 #if 0
2124     case AOP_PAGED:
2125       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2126       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2127 #endif
2128
2129     case AOP_REG:
2130       {
2131         int rIdx;
2132
2133 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
2134 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
2135         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2136
2137         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2138         
2139         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2140 //      pcop->type = PO_GPR_REGISTER;
2141         PCOR(pcop)->rIdx = rIdx;
2142         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2143         PCOR(pcop)->r->wasUsed=1;
2144         PCOR(pcop)->r->isFree=0;
2145
2146         PCOR(pcop)->instance = offset;
2147         pcop->type = PCOR(pcop)->r->pc_type;
2148         
2149         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2150 //      rs = aop->aopu.aop_reg[offset]->name;
2151 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2152         return pcop;
2153       }
2154
2155     case AOP_CRY:
2156         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2157
2158       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2159       PCOR(pcop)->instance = offset;
2160       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2161       //if(PCOR(pcop)->r == NULL)
2162       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2163       return pcop;
2164         
2165     case AOP_LIT:
2166         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2167       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2168
2169     case AOP_STR:
2170       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2171       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2172
2173       /*
2174       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2175       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2176       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2177       pcop->type = PCOR(pcop)->r->pc_type;
2178       pcop->name = PCOR(pcop)->r->name;
2179
2180       return pcop;
2181       */
2182
2183     case AOP_PCODE:
2184       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2185                           __LINE__, 
2186                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2187       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2188       switch( aop->aopu.pcop->type ) {
2189         case PO_DIR: PCOR(pcop)->instance += offset; break;
2190         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2191         case PO_WREG:
2192             assert (offset==0);
2193             break;
2194         default:
2195           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2196           assert( 0 );  /* should never reach here */;
2197       }
2198       return pcop;
2199     }
2200
2201     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2202            "pic16_popGet got unsupported aop->type");
2203     exit(0);
2204 }
2205 /*-----------------------------------------------------------------*/
2206 /* pic16_aopPut - puts a string for a aop                                */
2207 /*-----------------------------------------------------------------*/
2208 void pic16_aopPut (asmop *aop, char *s, int offset)
2209 {
2210     char *d = buffer ;
2211     symbol *lbl ;
2212
2213     return;
2214
2215     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2216
2217     if (aop->size && offset > ( aop->size - 1)) {
2218         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2219                "pic16_aopPut got offset > aop->size");
2220         exit(0);
2221     }
2222
2223     /* will assign value to value */
2224     /* depending on where it is ofcourse */
2225     switch (aop->type) {
2226     case AOP_DIR:
2227       if (offset) {
2228         sprintf(d,"(%s + %d)",
2229                 aop->aopu.aop_dir,offset);
2230         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2231
2232       } else
2233             sprintf(d,"%s",aop->aopu.aop_dir);
2234         
2235         if (strcmp(d,s)) {
2236           DEBUGpic16_emitcode(";","%d",__LINE__);
2237           if(strcmp(s,"W"))
2238             pic16_emitcode("movf","%s,w",s);
2239           pic16_emitcode("movwf","%s",d);
2240
2241           if(strcmp(s,"W")) {
2242             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2243             if(offset >= aop->size) {
2244               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2245               break;
2246             } else
2247               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2248           }
2249
2250           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2251
2252
2253         }
2254         break;
2255         
2256     case AOP_REG:
2257       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2258         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2259           /*
2260             if (*s == '@'           ||
2261                 strcmp(s,"r0") == 0 ||
2262                 strcmp(s,"r1") == 0 ||
2263                 strcmp(s,"r2") == 0 ||
2264                 strcmp(s,"r3") == 0 ||
2265                 strcmp(s,"r4") == 0 ||
2266                 strcmp(s,"r5") == 0 ||
2267                 strcmp(s,"r6") == 0 || 
2268                 strcmp(s,"r7") == 0 )
2269                 pic16_emitcode("mov","%s,%s  ; %d",
2270                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2271             else
2272           */
2273
2274           if(strcmp(s,"W")==0 )
2275             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2276
2277           pic16_emitcode("movwf","%s",
2278                    aop->aopu.aop_reg[offset]->name);
2279
2280           if(strcmp(s,zero)==0) {
2281             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2282
2283           } else if(strcmp(s,"W")==0) {
2284             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2285             pcop->type = PO_GPR_REGISTER;
2286
2287             PCOR(pcop)->rIdx = -1;
2288             PCOR(pcop)->r = NULL;
2289
2290             DEBUGpic16_emitcode(";","%d",__LINE__);
2291             pcop->name = Safe_strdup(s);
2292             pic16_emitpcode(POC_MOVFW,pcop);
2293             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2294           } else if(strcmp(s,one)==0) {
2295             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2296             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2297           } else {
2298             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2299           }
2300         }
2301         break;
2302         
2303     case AOP_DPTR:
2304     case AOP_DPTR2:
2305     
2306     if (aop->type == AOP_DPTR2)
2307     {
2308         genSetDPTR(1);
2309     }
2310     
2311         if (aop->code) {
2312             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2313                    "pic16_aopPut writting to code space");
2314             exit(0);
2315         }
2316         
2317         while (offset > aop->coff) {
2318             aop->coff++;
2319             pic16_emitcode ("inc","dptr");
2320         }
2321         
2322         while (offset < aop->coff) {
2323             aop->coff-- ;
2324             pic16_emitcode("lcall","__decdptr");
2325         }
2326         
2327         aop->coff = offset;
2328         
2329         /* if not in accumulater */
2330         MOVA(s);        
2331         
2332         pic16_emitcode ("movx","@dptr,a");
2333         
2334     if (aop->type == AOP_DPTR2)
2335     {
2336         genSetDPTR(0);
2337     }
2338         break;
2339         
2340     case AOP_R0:
2341     case AOP_R1:
2342         while (offset > aop->coff) {
2343             aop->coff++;
2344             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2345         }
2346         while (offset < aop->coff) {
2347             aop->coff-- ;
2348             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2349         }
2350         aop->coff = offset;
2351         
2352         if (aop->paged) {
2353             MOVA(s);           
2354             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2355             
2356         } else
2357             if (*s == '@') {
2358                 MOVA(s);
2359                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2360             } else
2361                 if (strcmp(s,"r0") == 0 ||
2362                     strcmp(s,"r1") == 0 ||
2363                     strcmp(s,"r2") == 0 ||
2364                     strcmp(s,"r3") == 0 ||
2365                     strcmp(s,"r4") == 0 ||
2366                     strcmp(s,"r5") == 0 ||
2367                     strcmp(s,"r6") == 0 || 
2368                     strcmp(s,"r7") == 0 ) {
2369                     char buffer[10];
2370                     sprintf(buffer,"a%s",s);
2371                     pic16_emitcode("mov","@%s,%s",
2372                              aop->aopu.aop_ptr->name,buffer);
2373                 } else
2374                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2375         
2376         break;
2377         
2378     case AOP_STK:
2379         if (strcmp(s,"a") == 0)
2380             pic16_emitcode("push","acc");
2381         else
2382             pic16_emitcode("push","%s",s);
2383         
2384         break;
2385         
2386     case AOP_CRY:
2387         /* if bit variable */
2388         if (!aop->aopu.aop_dir) {
2389             pic16_emitcode("clr","a");
2390             pic16_emitcode("rlc","a");
2391         } else {
2392             if (s == zero) 
2393                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2394             else
2395                 if (s == one)
2396                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2397                 else
2398                     if (!strcmp(s,"c"))
2399                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2400                     else {
2401                         lbl = newiTempLabel(NULL);
2402                         
2403                         if (strcmp(s,"a")) {
2404                             MOVA(s);
2405                         }
2406                         pic16_emitcode("clr","c");
2407                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2408                         pic16_emitcode("cpl","c");
2409                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2410                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2411                     }
2412         }
2413         break;
2414         
2415     case AOP_STR:
2416         aop->coff = offset;
2417         if (strcmp(aop->aopu.aop_str[offset],s))
2418             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2419         break;
2420         
2421     case AOP_ACC:
2422         aop->coff = offset;
2423         if (!offset && (strcmp(s,"acc") == 0))
2424             break;
2425         
2426         if (strcmp(aop->aopu.aop_str[offset],s))
2427             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2428         break;
2429
2430     default :
2431         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2432 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2433 //             "pic16_aopPut got unsupported aop->type");
2434 //      exit(0);    
2435     }    
2436
2437 }
2438
2439 /*-----------------------------------------------------------------*/
2440 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2441 /*-----------------------------------------------------------------*/
2442 void pic16_mov2w (asmop *aop, int offset)
2443 {
2444   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2445
2446   if(is_LitAOp(aop))
2447     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2448   else
2449     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2450 }
2451
2452 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2453 {
2454   if(is_LitAOp(src)) {
2455     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2456     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2457   } else {
2458     if(pic16_sameRegsOfs(src, dst, offset))return;
2459     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2460                       pic16_popGet(dst, offset)));
2461   }
2462 }
2463
2464 static void pic16_movLit2f(pCodeOp *pc, int lit)
2465 {
2466   if (0 == (lit & 0x00ff))
2467   {
2468     pic16_emitpcode (POC_CLRF, pc);
2469   } else if (0xff == (lit & 0x00ff))
2470   {
2471     pic16_emitpcode (POC_SETF, pc);
2472   } else {
2473     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2474     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2475   }
2476 }
2477
2478 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2479 {
2480   if(is_LitAOp(src)) {
2481     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2482     pic16_emitpcode(POC_MOVWF, dst);
2483   } else {
2484     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2485   }
2486 }
2487
2488 void pic16_testStackOverflow(void)
2489 {
2490 #define GSTACK_TEST_NAME        "_gstack_test"
2491
2492   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2493   
2494   {
2495     symbol *sym;
2496
2497       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2498       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2499 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2500       checkAddSym(&externs, sym);
2501   }
2502
2503 }
2504
2505 /* push pcop into stack */
2506 void pic16_pushpCodeOp(pCodeOp *pcop)
2507 {
2508 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2509   if (pcop->type == PO_LITERAL) {
2510     pic16_emitpcode(POC_MOVLW, pcop);
2511     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2512   } else {
2513     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2514   }
2515   if(pic16_options.gstack)
2516     pic16_testStackOverflow();
2517     
2518 }
2519
2520 /* pop pcop from stack */
2521 void pic16_poppCodeOp(pCodeOp *pcop)
2522 {
2523   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2524   if(pic16_options.gstack)
2525     pic16_testStackOverflow();
2526 }
2527
2528
2529 /*-----------------------------------------------------------------*/
2530 /* pushw - pushes wreg to stack                                    */
2531 /*-----------------------------------------------------------------*/
2532 void pushw(void)
2533 {
2534   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2535   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2536   if(pic16_options.gstack)
2537     pic16_testStackOverflow();
2538 }
2539
2540                 
2541 /*-----------------------------------------------------------------*/
2542 /* pushaop - pushes aop to stack                                   */
2543 /*-----------------------------------------------------------------*/
2544 void pushaop(asmop *aop, int offset)
2545 {
2546   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2547
2548   if(_G.resDirect)return;
2549   
2550   if(is_LitAOp(aop)) {
2551     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2552     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2553   } else {
2554     pic16_emitpcode(POC_MOVFF,
2555       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2556   }
2557
2558   if(pic16_options.gstack)
2559     pic16_testStackOverflow();
2560 }
2561
2562 /*-----------------------------------------------------------------*/
2563 /* popaop - pops aop from stack                                    */
2564 /*-----------------------------------------------------------------*/
2565 void popaop(asmop *aop, int offset)
2566 {
2567   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2568   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2569   if(pic16_options.gstack)
2570     pic16_testStackOverflow();
2571 }
2572
2573 void popaopidx(asmop *aop, int offset, int index)
2574 {
2575   int ofs=1;
2576
2577     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2578
2579     if(STACK_MODEL_LARGE)ofs++;
2580
2581     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2582     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2583     if(pic16_options.gstack)
2584       pic16_testStackOverflow();
2585 }
2586
2587 #if !(USE_GENERIC_SIGNED_SHIFT)
2588 /*-----------------------------------------------------------------*/
2589 /* reAdjustPreg - points a register back to where it should        */
2590 /*-----------------------------------------------------------------*/
2591 static void reAdjustPreg (asmop *aop)
2592 {
2593     int size ;
2594
2595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2596     aop->coff = 0;
2597     if ((size = aop->size) <= 1)
2598         return ;
2599     size-- ;
2600     switch (aop->type) {
2601         case AOP_R0 :
2602         case AOP_R1 :
2603             while (size--)
2604                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2605             break;          
2606         case AOP_DPTR :
2607         case AOP_DPTR2:
2608             if (aop->type == AOP_DPTR2)
2609             {
2610                 genSetDPTR(1);
2611             } 
2612             while (size--)
2613             {
2614                 pic16_emitcode("lcall","__decdptr");
2615             }
2616                 
2617             if (aop->type == AOP_DPTR2)
2618             {
2619                 genSetDPTR(0);
2620             }                
2621             break;  
2622
2623     }   
2624
2625 }
2626 #endif
2627
2628 #if 0
2629 /*-----------------------------------------------------------------*/
2630 /* opIsGptr: returns non-zero if the passed operand is             */   
2631 /* a generic pointer type.                                         */
2632 /*-----------------------------------------------------------------*/ 
2633 static int opIsGptr(operand *op)
2634 {
2635     sym_link *type = operandType(op);
2636     
2637     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2638     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2639     {
2640         return 1;
2641     }
2642     return 0;        
2643 }
2644 #endif
2645
2646 /*-----------------------------------------------------------------*/
2647 /* pic16_getDataSize - get the operand data size                         */
2648 /*-----------------------------------------------------------------*/
2649 int pic16_getDataSize(operand *op)
2650 {
2651     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2652
2653
2654     return AOP_SIZE(op);
2655
2656     // tsd- in the pic port, the genptr size is 1, so this code here
2657     // fails. ( in the 8051 port, the size was 4).
2658 #if 0
2659     int size;
2660     size = AOP_SIZE(op);
2661     if (size == GPTRSIZE)
2662     {
2663         sym_link *type = operandType(op);
2664         if (IS_GENPTR(type))
2665         {
2666             /* generic pointer; arithmetic operations
2667              * should ignore the high byte (pointer type).
2668              */
2669             size--;
2670     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2671         }
2672     }
2673     return size;
2674 #endif
2675 }
2676
2677 /*-----------------------------------------------------------------*/
2678 /* pic16_outAcc - output Acc                                             */
2679 /*-----------------------------------------------------------------*/
2680 void pic16_outAcc(operand *result)
2681 {
2682   int size,offset;
2683   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2684   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2685
2686
2687   size = pic16_getDataSize(result);
2688   if(size){
2689     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2690     size--;
2691     offset = 1;
2692     /* unsigned or positive */
2693     while(size--)
2694       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2695   }
2696
2697 }
2698
2699 /*-----------------------------------------------------------------*/
2700 /* pic16_outBitC - output a bit C                                  */
2701 /*                 Move to result the value of Carry flag -- VR    */
2702 /*-----------------------------------------------------------------*/
2703 void pic16_outBitC(operand *result)
2704 {
2705   int i;
2706
2707     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2708
2709     /* if the result is bit */
2710     if (AOP_TYPE(result) == AOP_CRY) {
2711         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2712         pic16_aopPut(AOP(result),"c",0);
2713     } else {
2714
2715         i = AOP_SIZE(result);
2716         while(i--) {
2717                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2718         }
2719         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2720     }
2721 }
2722
2723 /*-----------------------------------------------------------------*/
2724 /* pic16_outBitOp - output a bit from Op                           */
2725 /*                 Move to result the value of set/clr op -- VR    */
2726 /*-----------------------------------------------------------------*/
2727 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2728 {
2729   int i;
2730
2731     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2732
2733     /* if the result is bit */
2734     if (AOP_TYPE(result) == AOP_CRY) {
2735         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2736         pic16_aopPut(AOP(result),"c",0);
2737     } else {
2738
2739         i = AOP_SIZE(result);
2740         while(i--) {
2741                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2742         }
2743         pic16_emitpcode(POC_RRCF, pcop);          
2744         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2745     }
2746 }
2747
2748 /*-----------------------------------------------------------------*/
2749 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2750 /*-----------------------------------------------------------------*/
2751 void pic16_toBoolean(operand *oper)
2752 {
2753     int size = AOP_SIZE(oper) - 1;
2754     int offset = 1;
2755
2756     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2757
2758     if ( AOP_TYPE(oper) != AOP_ACC) {
2759       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2760     }
2761     while (size--) {
2762       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2763     }
2764 }
2765
2766 /*-----------------------------------------------------------------*/
2767 /* genUminusFloat - unary minus for floating points                */
2768 /*-----------------------------------------------------------------*/
2769 static void genUminusFloat(operand *op,operand *result)
2770 {
2771   int size ,offset =0 ;
2772   
2773     FENTRY;
2774     /* for this we just need to flip the 
2775     first it then copy the rest in place */
2776     size = AOP_SIZE(op);
2777     assert( size == AOP_SIZE(result) );
2778
2779     while(size--) {
2780       pic16_mov2f(AOP(result), AOP(op), offset);
2781       offset++;
2782     }
2783     
2784     /* toggle the MSB's highest bit */
2785     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2786 }
2787
2788 /*-----------------------------------------------------------------*/
2789 /* genUminus - unary minus code generation                         */
2790 /*-----------------------------------------------------------------*/
2791 static void genUminus (iCode *ic)
2792 {
2793   int size, i;
2794   sym_link *optype, *rtype;
2795   symbol *label;
2796   int needLabel=0;
2797
2798     FENTRY;     
2799     
2800     /* assign asmops */
2801     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2802     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2803
2804     /* if both in bit space then special case */
2805     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2806       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2807         
2808         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2809         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2810         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2811         goto release; 
2812     } 
2813
2814     optype = operandType(IC_LEFT(ic));
2815     rtype = operandType(IC_RESULT(ic));
2816
2817
2818     /* if float then do float stuff */
2819     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2820       if(IS_FIXED(optype))
2821         debugf("implement fixed16x16 type\n", 0);
2822         
2823         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2824         goto release;
2825     }
2826
2827     /* otherwise subtract from zero by taking the 2's complement */
2828     size = AOP_SIZE(IC_LEFT(ic));
2829     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2830     label = newiTempLabel ( NULL );
2831     
2832     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2833       for (i=size-1; i > 0; i--) {
2834         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2835       } // for
2836       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2837       for (i=1; i < size; i++) {
2838         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2839         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2840       } // for
2841     } else {
2842       for (i=size-1; i >= 0; i--) {
2843         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2844         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2845       } // for
2846       if (size > 1) {
2847         for (i=0; i < size-2; i++) {
2848           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2849           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2850         } // for
2851         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2852       } // if
2853       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2854     }
2855     if (needLabel)
2856       pic16_emitpLabel (label->key);
2857
2858 release:
2859     /* release the aops */
2860     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2861     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2862 }
2863
2864 #if 0
2865 /*-----------------------------------------------------------------*/
2866 /* saveRegisters - will look for a call and save the registers     */
2867 /*-----------------------------------------------------------------*/
2868 static void saveRegisters(iCode *lic) 
2869 {
2870     int i;
2871     iCode *ic;
2872     bitVect *rsave;
2873     sym_link *dtype;
2874
2875     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2876     /* look for call */
2877     for (ic = lic ; ic ; ic = ic->next) 
2878         if (ic->op == CALL || ic->op == PCALL)
2879             break;
2880
2881     if (!ic) {
2882         fprintf(stderr,"found parameter push with no function call\n");
2883         return ;
2884     }
2885
2886     /* if the registers have been saved already then
2887     do nothing */
2888     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2889         return ;
2890
2891     /* find the registers in use at this time 
2892     and push them away to safety */
2893     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2894                           ic->rUsed);
2895
2896     ic->regsSaved = 1;
2897     if (options.useXstack) {
2898         if (bitVectBitValue(rsave,R0_IDX))
2899             pic16_emitcode("mov","b,r0");
2900         pic16_emitcode("mov","r0,%s",spname);
2901         for (i = 0 ; i < pic16_nRegs ; i++) {
2902             if (bitVectBitValue(rsave,i)) {
2903                 if (i == R0_IDX)
2904                     pic16_emitcode("mov","a,b");
2905                 else
2906                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2907                 pic16_emitcode("movx","@r0,a");
2908                 pic16_emitcode("inc","r0");
2909             }
2910         }
2911         pic16_emitcode("mov","%s,r0",spname);
2912         if (bitVectBitValue(rsave,R0_IDX))
2913             pic16_emitcode("mov","r0,b");           
2914     }// else
2915     //for (i = 0 ; i < pic16_nRegs ; i++) {
2916     //    if (bitVectBitValue(rsave,i))
2917     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2918     //}
2919
2920     dtype = operandType(IC_LEFT(ic));
2921     if (currFunc && dtype && 
2922         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2923         IFFUNC_ISISR(currFunc->type) &&
2924         !ic->bankSaved) 
2925
2926         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2927
2928 }
2929 /*-----------------------------------------------------------------*/
2930 /* unsaveRegisters - pop the pushed registers                      */
2931 /*-----------------------------------------------------------------*/
2932 static void unsaveRegisters (iCode *ic)
2933 {
2934     int i;
2935     bitVect *rsave;
2936
2937     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2938     /* find the registers in use at this time 
2939     and push them away to safety */
2940     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2941                           ic->rUsed);
2942     
2943     if (options.useXstack) {
2944         pic16_emitcode("mov","r0,%s",spname);   
2945         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2946             if (bitVectBitValue(rsave,i)) {
2947                 pic16_emitcode("dec","r0");
2948                 pic16_emitcode("movx","a,@r0");
2949                 if (i == R0_IDX)
2950                     pic16_emitcode("mov","b,a");
2951                 else
2952                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2953             }       
2954
2955         }
2956         pic16_emitcode("mov","%s,r0",spname);
2957         if (bitVectBitValue(rsave,R0_IDX))
2958             pic16_emitcode("mov","r0,b");
2959     } //else
2960     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2961     //    if (bitVectBitValue(rsave,i))
2962     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2963     //}
2964
2965 }  
2966 #endif
2967
2968 #if 0  // patch 14
2969 /*-----------------------------------------------------------------*/
2970 /* pushSide -                                                      */
2971 /*-----------------------------------------------------------------*/
2972 static void pushSide(operand * oper, int size)
2973 {
2974         int offset = 0;
2975     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2976         while (size--) {
2977                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2978                 if (AOP_TYPE(oper) != AOP_REG &&
2979                     AOP_TYPE(oper) != AOP_DIR &&
2980                     strcmp(l,"a") ) {
2981                         pic16_emitcode("mov","a,%s",l);
2982                         pic16_emitcode("push","acc");
2983                 } else
2984                         pic16_emitcode("push","%s",l);
2985         }
2986 }
2987 #endif // patch 14
2988
2989 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2990 {
2991   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2992     pic16_emitpcode(POC_MOVFW, src);
2993     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2994   } else {
2995     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2996         src, pic16_popGet(AOP(op), offset)));
2997   }
2998 }
2999
3000
3001 /*-----------------------------------------------------------------*/
3002 /* assignResultValue - assign results to oper, rescall==1 is       */
3003 /*                     called from genCall() or genPcall()         */
3004 /*-----------------------------------------------------------------*/
3005 static void assignResultValue(operand * oper, int res_size, int rescall)
3006 {
3007   int size = AOP_SIZE(oper);
3008   int offset=0;
3009   
3010     FENTRY2;
3011 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3012     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3013
3014     if(rescall) {
3015       /* assign result from a call/pcall function() */
3016                 
3017       /* function results are stored in a special order,
3018        * see top of file with Function return policy, or manual */
3019
3020       if(size <= 4) {
3021         /* 8-bits, result in WREG */
3022         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3023                         
3024         if(size > 1 && res_size > 1) {
3025           /* 16-bits, result in PRODL:WREG */
3026           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3027         }
3028                         
3029         if(size > 2 && res_size > 2) {
3030           /* 24-bits, result in PRODH:PRODL:WREG */
3031           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3032         }
3033                         
3034         if(size > 3 && res_size > 3) {
3035           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3036           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3037         }
3038
3039         pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
3040       
3041       } else {
3042         /* >32-bits, result on stack, and FSR0 points to beginning.
3043          * Fix stack when done */
3044         /* FIXME FIXME */
3045 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3046         while (size--) {
3047 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3048 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3049                 
3050           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3051           GpsuedoStkPtr++;
3052         }
3053                         
3054         /* fix stack */
3055         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3056         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3057         if(STACK_MODEL_LARGE) {
3058           emitSKPNC;
3059           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3060         }
3061       }                 
3062     } else {
3063       int areg = 0;             /* matching argument register */
3064       
3065 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3066       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3067
3068
3069       /* its called from genReceive (probably) -- VR */
3070       /* I hope this code will not be called from somewhere else in the future! 
3071        * We manually set the pseudo stack pointer in genReceive. - dw
3072        */
3073       if(!GpsuedoStkPtr && _G.useWreg) {
3074 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3075
3076         /* The last byte in the assignment is in W */
3077         if(areg <= GpsuedoStkPtr) {
3078           size--;
3079           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3080           offset++;
3081 //          debugf("receive from WREG\n", 0);
3082         }
3083         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3084       }
3085 //      GpsuedoStkPtr++;
3086       _G.stack_lat = AOP_SIZE(oper)-1;
3087
3088       while (size) {
3089         size--;
3090         GpsuedoStkPtr++;
3091         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3092 //        debugf("receive from STACK\n", 0);
3093         offset++;
3094       }
3095     }
3096 }
3097
3098
3099 /*-----------------------------------------------------------------*/
3100 /* genIpush - generate code for pushing this gets a little complex */
3101 /*-----------------------------------------------------------------*/
3102 static void genIpush (iCode *ic)
3103 {
3104 //  int size, offset=0;
3105
3106   FENTRY;
3107   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3108
3109   if(ic->parmPush) {
3110     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3111
3112     /* send to stack as normal */
3113     addSet(&_G.sendSet,ic);
3114 //    addSetHead(&_G.sendSet,ic);
3115     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3116   }
3117
3118         
3119 #if 0
3120     int size, offset = 0 ;
3121     char *l;
3122
3123
3124     /* if this is not a parm push : ie. it is spill push 
3125     and spill push is always done on the local stack */
3126     if (!ic->parmPush) {
3127
3128         /* and the item is spilt then do nothing */
3129         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3130             return ;
3131
3132         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3133         size = AOP_SIZE(IC_LEFT(ic));
3134         /* push it on the stack */
3135         while(size--) {
3136             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3137             if (*l == '#') {
3138                 MOVA(l);
3139                 l = "acc";
3140             }
3141             pic16_emitcode("push","%s",l);
3142         }
3143         return ;        
3144     }
3145
3146     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3147 #endif
3148 }
3149
3150 /*-----------------------------------------------------------------*/
3151 /* genIpop - recover the registers: can happen only for spilling   */
3152 /*-----------------------------------------------------------------*/
3153 static void genIpop (iCode *ic)
3154 {
3155   FENTRY;
3156   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3157 #if 0
3158     int size,offset ;
3159
3160
3161     /* if the temp was not pushed then */
3162     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3163         return ;
3164
3165     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3166     size = AOP_SIZE(IC_LEFT(ic));
3167     offset = (size-1);
3168     while (size--) 
3169         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3170                                    FALSE,TRUE));
3171
3172     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3173 #endif
3174 }
3175
3176 #if 0
3177 /*-----------------------------------------------------------------*/
3178 /* unsaverbank - restores the resgister bank from stack            */
3179 /*-----------------------------------------------------------------*/
3180 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3181 {
3182   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3183 #if 0
3184     int i;
3185     asmop *aop ;
3186     regs *r = NULL;
3187
3188     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3189     if (popPsw) {
3190         if (options.useXstack) {
3191             aop = newAsmop(0);
3192             r = getFreePtr(ic,&aop,FALSE);
3193             
3194             
3195             pic16_emitcode("mov","%s,_spx",r->name);
3196             pic16_emitcode("movx","a,@%s",r->name);
3197             pic16_emitcode("mov","psw,a");
3198             pic16_emitcode("dec","%s",r->name);
3199             
3200         }else
3201             pic16_emitcode ("pop","psw");
3202     }
3203
3204     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3205         if (options.useXstack) {       
3206             pic16_emitcode("movx","a,@%s",r->name);
3207             //pic16_emitcode("mov","(%s+%d),a",
3208             //       regspic16[i].base,8*bank+regspic16[i].offset);
3209             pic16_emitcode("dec","%s",r->name);
3210
3211         } else 
3212           pic16_emitcode("pop",""); //"(%s+%d)",
3213         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3214     }
3215
3216     if (options.useXstack) {
3217
3218         pic16_emitcode("mov","_spx,%s",r->name);
3219         pic16_freeAsmop(NULL,aop,ic,TRUE);
3220
3221     }
3222 #endif 
3223 }
3224
3225 /*-----------------------------------------------------------------*/
3226 /* saverbank - saves an entire register bank on the stack          */
3227 /*-----------------------------------------------------------------*/
3228 static void saverbank (int bank, iCode *ic, bool pushPsw)
3229 {
3230   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3231 #if 0
3232     int i;
3233     asmop *aop ;
3234     regs *r = NULL;
3235
3236     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3237     if (options.useXstack) {
3238
3239         aop = newAsmop(0);
3240         r = getFreePtr(ic,&aop,FALSE);  
3241         pic16_emitcode("mov","%s,_spx",r->name);
3242
3243     }
3244
3245     for (i = 0 ; i < pic16_nRegs ;i++) {
3246         if (options.useXstack) {
3247             pic16_emitcode("inc","%s",r->name);
3248             //pic16_emitcode("mov","a,(%s+%d)",
3249             //         regspic16[i].base,8*bank+regspic16[i].offset);
3250             pic16_emitcode("movx","@%s,a",r->name);           
3251         } else 
3252           pic16_emitcode("push","");// "(%s+%d)",
3253                      //regspic16[i].base,8*bank+regspic16[i].offset);
3254     }
3255     
3256     if (pushPsw) {
3257         if (options.useXstack) {
3258             pic16_emitcode("mov","a,psw");
3259             pic16_emitcode("movx","@%s,a",r->name);     
3260             pic16_emitcode("inc","%s",r->name);
3261             pic16_emitcode("mov","_spx,%s",r->name);       
3262             pic16_freeAsmop (NULL,aop,ic,TRUE);
3263             
3264         } else
3265             pic16_emitcode("push","psw");
3266         
3267         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3268     }
3269     ic->bankSaved = 1;
3270 #endif
3271 }
3272 #endif  /* 0 */
3273
3274
3275 static int wparamCmp(void *p1, void *p2)
3276 {
3277   return (!strcmp((char *)p1, (char *)p2));
3278 }
3279
3280 int inWparamList(char *s)
3281 {
3282   return isinSetWith(wparamList, s, wparamCmp);
3283
3284
3285
3286 /*-----------------------------------------------------------------*/
3287 /* genCall - generates a call statement                            */
3288 /*-----------------------------------------------------------------*/
3289 static void genCall (iCode *ic)
3290 {
3291   sym_link *ftype;   
3292   int stackParms=0;
3293   int use_wreg=0;
3294   int inwparam=0;
3295   char *fname;
3296   
3297     FENTRY;
3298
3299     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3300     /* if caller saves & we have not saved then */
3301 //    if (!ic->regsSaved)
3302 //      saveRegisters(ic);
3303
3304         /* initialise stackParms for IPUSH pushes */
3305 //      stackParms = psuedoStkPtr;
3306 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3307     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3308     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3309
3310 #if 0
3311     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3312 #endif
3313
3314     /* if send set is not empty the assign */
3315     if (_G.sendSet) {
3316       iCode *sic;
3317       int psuedoStkPtr=-1; 
3318       int firstTimeThruLoop = 1;
3319
3320
3321         /* reverse sendSet if function is not reentrant */
3322         if(!IFFUNC_ISREENT(ftype))
3323           _G.sendSet = reverseSet(_G.sendSet);
3324
3325         /* First figure how many parameters are getting passed */
3326         stackParms = 0;
3327         use_wreg = 0;
3328         
3329         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3330           int size;
3331 //          int offset = 0;
3332
3333             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3334             size = AOP_SIZE(IC_LEFT(sic));
3335
3336             stackParms += size;
3337
3338             /* pass the last byte through WREG */
3339             if(inwparam) {
3340
3341               while (size--) {
3342                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3343                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3344                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3345
3346                 if(!firstTimeThruLoop) {
3347                   /* If this is not the first time we've been through the loop
3348                    * then we need to save the parameter in a temporary
3349                    * register. The last byte of the last parameter is
3350                    * passed in W. */
3351
3352                   pushw();
3353 //                  --psuedoStkPtr;             // sanity check
3354                   use_wreg = 1;
3355                 }
3356                 
3357                 firstTimeThruLoop=0;
3358
3359                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3360
3361 //                offset++;
3362               }
3363             } else {
3364               /* all arguments are passed via stack */
3365               use_wreg = 0;
3366
3367               while (size--) {
3368                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3369                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3370                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3371
3372 //                pushaop(AOP(IC_LEFT(sic)), size);
3373                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3374                                 
3375                 if(!_G.resDirect)
3376                   pushw();
3377               }
3378             }
3379
3380             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3381           }
3382
3383           if(inwparam) {
3384             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3385               pushw();  /* save last parameter to stack if functions has varargs */
3386               use_wreg = 0;
3387             } else
3388               use_wreg = 1;
3389           } else use_wreg = 0;
3390
3391           _G.stackRegSet = _G.sendSet;
3392           _G.sendSet = NULL;
3393     }
3394
3395     /* make the call */
3396     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3397
3398     GpsuedoStkPtr=0;
3399     
3400     /* if we need to assign a result value */
3401     if ((IS_ITEMP(IC_RESULT(ic))
3402           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3403               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3404         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3405
3406       _G.accInUse++;
3407       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3408       _G.accInUse--;
3409
3410       /* Must not assign an 8-bit result to a 16-bit variable;
3411        * this would use (used...) the uninitialized PRODL! */
3412       /* FIXME: Need a proper way to obtain size of function result type,
3413        * OP_SYM_ETYPE does not work: it dereferences pointer types! */
3414       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
3415
3416       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3417                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3418                 
3419       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3420     }
3421
3422     if(!stackParms && ic->parmBytes) {
3423       stackParms = ic->parmBytes;
3424     }
3425       
3426     stackParms -= use_wreg;
3427     
3428     if(stackParms>0) {
3429       if(stackParms == 1) {
3430         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3431       } else {
3432         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3433         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3434       }
3435       if(STACK_MODEL_LARGE) {
3436         emitSKPNC;
3437         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3438       }
3439     }
3440
3441 #if 0
3442     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3443 #endif
3444
3445     /* adjust the stack for parameters if required */
3446 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3447
3448 #if 0
3449       /* if register bank was saved then pop them */
3450       if (ic->bankSaved)
3451         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3452
3453       /* if we hade saved some registers then unsave them */
3454       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3455         unsaveRegisters (ic);
3456 #endif
3457 }
3458
3459
3460
3461 /*-----------------------------------------------------------------*/
3462 /* genPcall - generates a call by pointer statement                */
3463 /*            new version, created from genCall - HJD              */
3464 /*-----------------------------------------------------------------*/
3465 static void genPcall (iCode *ic)
3466 {
3467   sym_link *fntype;
3468   int stackParms=0;
3469   symbol *retlbl = newiTempLabel(NULL);
3470   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3471   
3472     FENTRY;
3473
3474     fntype = operandType( IC_LEFT(ic) )->next;
3475
3476     /* if send set is not empty the assign */
3477     if (_G.sendSet) {
3478       iCode *sic;
3479       int psuedoStkPtr=-1; 
3480
3481       /* reverse sendSet if function is not reentrant */
3482       if(!IFFUNC_ISREENT(fntype))
3483         _G.sendSet = reverseSet(_G.sendSet);
3484
3485       stackParms = 0;
3486       
3487       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3488         int size;
3489
3490           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3491           size = AOP_SIZE(IC_LEFT(sic));
3492           stackParms += size;
3493
3494           /* all parameters are passed via stack, since WREG is clobbered
3495            * by the calling sequence */
3496           while (size--) {
3497             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3498             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3499             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3500
3501             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3502             pushw();
3503           }
3504
3505           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3506       }
3507
3508       _G.stackRegSet = _G.sendSet;
3509       _G.sendSet = NULL;
3510     }
3511
3512     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3513
3514     // push return address
3515     // push $ on return stack, then replace with retlbl
3516
3517     /* Thanks to Thorsten Klose for pointing out that the following
3518      * snippet should be interrupt safe */
3519     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3520     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3521
3522     pic16_emitpcodeNULLop(POC_PUSH);
3523
3524     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3525     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3526     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3527     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3528     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3529     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3530
3531
3532     /* restore interrupt control register */
3533     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3534     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3535
3536     /* make the call by writing the pointer into pc */
3537     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3538     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3539
3540     // note: MOVFF to PCL not allowed
3541     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3542     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3543
3544
3545     /* return address is here: (X) */
3546     pic16_emitpLabelFORCE(retlbl->key);
3547
3548     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3549
3550     GpsuedoStkPtr=0;
3551     /* if we need assign a result value */
3552     if ((IS_ITEMP(IC_RESULT(ic))
3553           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3554               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3555         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3556
3557       _G.accInUse++;
3558       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3559       _G.accInUse--;
3560
3561       /* FIXME: Need proper way to obtain the function result's type.
3562        * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
3563       assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
3564
3565       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3566               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3567                 
3568       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3569     }
3570
3571 //    stackParms -= use_wreg;
3572     
3573     if(stackParms>0) {
3574       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3575       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3576       if(STACK_MODEL_LARGE) {
3577         emitSKPNC;
3578         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3579       }
3580     }
3581 }
3582
3583 /*-----------------------------------------------------------------*/
3584 /* resultRemat - result  is rematerializable                       */
3585 /*-----------------------------------------------------------------*/
3586 static int resultRemat (iCode *ic)
3587 {
3588   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3589   if (SKIP_IC(ic) || ic->op == IFX)
3590     return 0;
3591
3592   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3593     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3594     if (sym->remat && !POINTER_SET(ic)) 
3595       return 1;
3596   }
3597
3598   return 0;
3599 }
3600
3601 #if defined(__BORLANDC__) || defined(_MSC_VER)
3602 #define STRCASECMP stricmp
3603 #else
3604 #define STRCASECMP strcasecmp
3605 #endif
3606
3607 #if 0
3608 /*-----------------------------------------------------------------*/
3609 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3610 /*-----------------------------------------------------------------*/
3611 static bool inExcludeList(char *s)
3612 {
3613   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3614     int i =0;
3615     
3616     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3617     if (options.excludeRegs[i] &&
3618     STRCASECMP(options.excludeRegs[i],"none") == 0)
3619         return FALSE ;
3620
3621     for ( i = 0 ; options.excludeRegs[i]; i++) {
3622         if (options.excludeRegs[i] &&
3623         STRCASECMP(s,options.excludeRegs[i]) == 0)
3624             return TRUE;
3625     }
3626     return FALSE ;
3627 }
3628 #endif
3629
3630 /*-----------------------------------------------------------------*/
3631 /* genFunction - generated code for function entry                 */
3632 /*-----------------------------------------------------------------*/
3633 static void genFunction (iCode *ic)
3634 {
3635   symbol *sym;
3636   sym_link *ftype;
3637   
3638     FENTRY;
3639     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3640
3641     pic16_labelOffset += (max_key+4);
3642     max_key=0;
3643     GpsuedoStkPtr=0;
3644     _G.nRegsSaved = 0;
3645         
3646     ftype = operandType(IC_LEFT(ic));
3647     sym = OP_SYMBOL(IC_LEFT(ic));
3648
3649     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3650       /* create an absolute section at the interrupt vector:
3651        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3652       symbol *asym;
3653       char asymname[128];
3654       pBlock *apb;
3655
3656 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3657
3658         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3659           sprintf(asymname, "ivec_%s", sym->name);
3660         else
3661           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3662   
3663         /* when an interrupt is declared as naked, do not emit the special
3664          * wrapper segment at vector address. The user should take care for
3665          * this instead. -- VR */
3666
3667         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3668           asym = newSymbol(asymname, 0);
3669           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3670           pic16_addpBlock( apb );
3671
3672           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3673           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3674           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3675           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3676           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3677                 
3678           /* mark the end of this tiny function */
3679           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3680         } else {
3681           sprintf(asymname, "%s", sym->rname);
3682         }
3683
3684         {
3685           absSym *abSym;
3686
3687             abSym = Safe_calloc(1, sizeof(absSym));
3688             strcpy(abSym->name, asymname);
3689
3690             switch( FUNC_INTNO(sym->type) ) {
3691               case 0: abSym->address = 0x000000; break;
3692               case 1: abSym->address = 0x000008; break;
3693               case 2: abSym->address = 0x000018; break;
3694               
3695               default:
3696 //                fprintf(stderr, "no interrupt number is given\n");
3697                 abSym->address = -1; break;
3698             }
3699
3700             /* relocate interrupt vectors if needed */
3701             if(abSym->address != -1)
3702               abSym->address += pic16_options.ivt_loc;
3703
3704             addSet(&absSymSet, abSym);
3705         }
3706     }
3707
3708     /* create the function header */
3709     pic16_emitcode(";","-----------------------------------------");
3710     pic16_emitcode(";"," function %s",sym->name);
3711     pic16_emitcode(";","-----------------------------------------");
3712
3713     /* prevent this symbol from being emitted as 'extern' */
3714     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3715
3716     pic16_emitcode("","%s:",sym->rname);
3717     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3718
3719     {
3720       absSym *ab;
3721
3722         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3723           if(!strcmp(ab->name, sym->rname)) {
3724             pic16_pBlockConvert2Absolute(pb);
3725             break;
3726           }
3727         }
3728     }
3729
3730     if(IFFUNC_ISNAKED(ftype)) {
3731       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3732       return;
3733     }
3734         
3735     /* if critical function then turn interrupts off */
3736     if (IFFUNC_ISCRITICAL(ftype)) {
3737       //pic16_emitcode("clr","ea");
3738     }
3739
3740     currFunc = sym;             /* update the currFunc symbol */
3741     _G.fregsUsed = sym->regsUsed;
3742     _G.sregsAlloc = newBitVect(128);
3743     
3744
3745     /* if this is an interrupt service routine then
3746      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3747     if (IFFUNC_ISISR(sym->type)) {
3748         _G.usefastretfie = 1;   /* use shadow registers by default */
3749         
3750         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3751         if(!FUNC_ISSHADOWREGS(sym->type)) {
3752           /* do not save WREG,STATUS,BSR for high priority interrupts
3753            * because they are stored in the hardware shadow registers already */
3754           _G.usefastretfie = 0;
3755           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3756           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3757           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3758         }
3759
3760         /* these should really be optimized somehow, because not all
3761          * interrupt handlers modify them */
3762         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3763         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3764         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3765         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3766         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3767         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3768         
3769 //        pic16_pBlockConvert2ISR(pb);
3770     }
3771
3772     /* emit code to setup stack frame if user enabled,
3773      * and function is not main() */
3774     
3775 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3776     if(strcmp(sym->name, "main")) {
3777       if(0 
3778         || !options.ommitFramePtr 
3779 //        || sym->regsUsed
3780         || IFFUNC_ARGS(sym->type)
3781         || FUNC_HASSTACKPARM(sym->etype)
3782         ) {
3783         /* setup the stack frame */
3784         if(STACK_MODEL_LARGE)
3785           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3786         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3787
3788         if(STACK_MODEL_LARGE)
3789           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3790         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3791       }
3792     }
3793
3794     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3795           && sym->stack) {
3796
3797       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3798
3799       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3800       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3801       emitSKPC;
3802       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3803     }
3804           
3805     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3806       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3807         _G.useWreg = 0;
3808       else
3809         _G.useWreg = 1;
3810     } else
3811       _G.useWreg = 0;
3812
3813     /* if callee-save to be used for this function
3814      * then save the registers being used in this function */
3815 //    if (IFFUNC_CALLEESAVES(sym->type))
3816     if(strcmp(sym->name, "main")) {
3817       int i;
3818
3819         /* if any registers used */
3820         if (sym->regsUsed) {
3821                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3822
3823           if(!xinst) {
3824             /* save the registers used */
3825             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3826             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3827               if (bitVectBitValue(sym->regsUsed,i)) {
3828 #if 0
3829                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3830 #endif
3831                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3832                 _G.nRegsSaved++;
3833
3834                 if(!pic16_regWithIdx(i)->wasUsed) {
3835                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3836                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3837                   pic16_regWithIdx(i)->wasUsed = 1;
3838                 }
3839               }
3840             }
3841           } else {
3842             
3843             /* xinst */
3844             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3845             for(i=0;i<sym->regsUsed->size;i++) {
3846               if(bitVectBitValue(sym->regsUsed, i)) {
3847                 _G.nRegsSaved++;
3848               }
3849             }
3850                         
3851 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3852           }
3853
3854           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3855
3856         }
3857     }
3858         
3859     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3860 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3861 }
3862
3863 /*-----------------------------------------------------------------*/
3864 /* genEndFunction - generates epilogue for functions               */
3865 /*-----------------------------------------------------------------*/
3866 static void genEndFunction (iCode *ic)
3867 {
3868   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3869
3870     FENTRY;
3871
3872     if(IFFUNC_ISNAKED(sym->type)) {
3873       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3874       return;
3875     }
3876
3877     _G.stack_lat = 0;
3878
3879     /* add code for ISCRITICAL */
3880     if(IFFUNC_ISCRITICAL(sym->type)) {
3881       /* if critical function, turn on interrupts */
3882       
3883       /* TODO: add code here -- VR */
3884     }
3885     
3886 //    sym->regsUsed = _G.fregsUsed;
3887     
3888     /* now we need to restore the registers */
3889     /* if any registers used */
3890
3891     /* first restore registers that might be used for stack access */
3892     if(_G.sregsAllocSet) {
3893     regs *sr;
3894     
3895       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3896       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3897         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3898       }
3899     }
3900
3901     if (strcmp(sym->name, "main") && sym->regsUsed) {
3902       int i;
3903
3904         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3905         /* restore registers used */
3906         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3907         for ( i = sym->regsUsed->size; i >= 0; i--) {
3908           if (bitVectBitValue(sym->regsUsed,i)) {
3909             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3910             _G.nRegsSaved--;
3911           }
3912         }
3913         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3914     }
3915
3916       
3917
3918     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3919           && sym->stack) {
3920       if (sym->stack == 1) {
3921         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3922         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3923       } else {
3924         // we have to add more than one...
3925         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3926         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3927         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3928         emitSKPNC;
3929         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3930         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3931         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3932       }
3933     }
3934
3935     if(strcmp(sym->name, "main")) {
3936       if(0
3937         || !options.ommitFramePtr
3938 //        || sym->regsUsed
3939         || IFFUNC_ARGS(sym->type)
3940         || FUNC_HASSTACKPARM(sym->etype)
3941         ) {
3942         /* restore stack frame */
3943         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3944         if(STACK_MODEL_LARGE)
3945           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3946       }
3947     }
3948
3949     _G.useWreg = 0;
3950
3951     if (IFFUNC_ISISR(sym->type)) {
3952       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3953       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3954       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3955       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3956       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3957       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3958
3959       if(!FUNC_ISSHADOWREGS(sym->type)) {
3960         /* do not restore interrupt vector for WREG,STATUS,BSR
3961          * for high priority interrupt, see genFunction */
3962         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3963         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3964         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3965       }
3966 //      _G.interruptvector = 0;         /* sanity check */
3967
3968
3969       /* if debug then send end of function */
3970 /*      if (options.debug && currFunc)  */
3971       if (currFunc) {
3972         debugFile->writeEndFunction (currFunc, ic, 1);
3973       }
3974         
3975       if(_G.usefastretfie)
3976         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3977       else
3978         pic16_emitpcodeNULLop(POC_RETFIE);
3979
3980       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3981       
3982       _G.usefastretfie = 0;
3983       return;
3984     }
3985
3986     if (IFFUNC_ISCRITICAL(sym->type)) {
3987       pic16_emitcode("setb","ea");
3988     }
3989
3990     /* if debug then send end of function */
3991     if (currFunc) {
3992       debugFile->writeEndFunction (currFunc, ic, 1);
3993     }
3994
3995     /* insert code to restore stack frame, if user enabled it
3996      * and function is not main() */
3997          
3998
3999     pic16_emitpcodeNULLop(POC_RETURN);
4000
4001     /* Mark the end of a function */
4002     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
4003 }
4004
4005
4006 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4007 {
4008   unsigned long lit=1;
4009   operand *op;
4010   
4011     op = IC_LEFT(ic);
4012   
4013     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4014     if(AOP_TYPE(op) == AOP_LIT) {
4015       if(!IS_FLOAT(operandType( op ))) {
4016         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4017       } else {
4018         union {
4019           unsigned long lit_int;
4020           float lit_float;
4021         } info;
4022         
4023         /* take care if literal is a float */
4024         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4025         lit = info.lit_int;
4026       }
4027     }
4028
4029     if (AOP_TYPE(op) == AOP_LIT) {
4030       /* FIXME: broken for
4031        *   char __at(0x456) foo;
4032        *   return &foo;
4033        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4034       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4035     } else if (AOP_TYPE(op) == AOP_PCODE
4036                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4037       /* char *s= "aaa"; return s; */
4038       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4039        *      that the generic pointer is interpreted correctly
4040        *      as referring to __code space, but this is fragile! */
4041       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4042       /* XXX: should check that dest != WREG */
4043       pic16_emitpcode(POC_MOVWF, dest);
4044     } else {
4045       if(dest->type == PO_WREG && (offset == 0)) {
4046         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4047         return;
4048       }
4049       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4050     }
4051 }
4052
4053 /*-----------------------------------------------------------------*/
4054 /* genRet - generate code for return statement                     */
4055 /*-----------------------------------------------------------------*/
4056 static void genRet (iCode *ic)
4057 {
4058   int size;
4059   operand *left;
4060
4061     FENTRY;
4062         /* if we have no return value then
4063          * just generate the "ret" */
4064         
4065         if (!IC_LEFT(ic)) 
4066                 goto jumpret;       
4067     
4068         /* we have something to return then
4069          * move the return value into place */
4070         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4071         size = AOP_SIZE(IC_LEFT(ic));
4072
4073         if(size <= 4) {
4074           if(size>3)
4075             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4076           
4077           if(size>2)
4078             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4079
4080           if(size>1)
4081             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4082           
4083           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4084
4085         } else {
4086                 /* >32-bits, setup stack and FSR0 */
4087                 while (size--) {
4088 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4089 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4090
4091                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4092
4093 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4094                         GpsuedoStkPtr++;
4095                 }
4096                         
4097                 /* setup FSR0 */
4098                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4099                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4100
4101                 if(STACK_MODEL_LARGE) {
4102                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4103                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4104                 } else {
4105                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4106                 }
4107         }
4108                                 
4109 #if 0
4110         /* old code, left here for reference -- VR */    
4111         while (size--) {
4112           char *l ;
4113
4114                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4115                         /* #NOCHANGE */
4116                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4117                         pic16_emitpcomment("push %s",l);
4118                         pushed++;
4119                 } else {
4120                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4121                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4122                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4123                         
4124                         if (strcmp(fReturn[offset],l)) {
4125                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4126                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4127                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4128                                 } else {
4129                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4130                                 }
4131                                 
4132                                 if(size) {
4133                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4134                                 }
4135                                 offset++;
4136                         }
4137                 }
4138         }    
4139
4140         if (pushed) {
4141                 while(pushed) {
4142                         pushed--;
4143                         if (strcmp(fReturn[pushed],"a"))
4144                                 pic16_emitcode("pop",fReturn[pushed]);
4145                         else
4146                                 pic16_emitcode("pop","acc");
4147                 }
4148         }
4149 #endif
4150
4151
4152         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4153     
4154 jumpret:
4155         /* generate a jump to the return label
4156          * if the next is not the return statement */
4157         if (!(ic->next && ic->next->op == LABEL
4158                 && IC_LABEL(ic->next) == returnLabel)) {
4159         
4160                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4161                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4162         }
4163 }
4164
4165 /*-----------------------------------------------------------------*/
4166 /* genLabel - generates a label                                    */
4167 /*-----------------------------------------------------------------*/
4168 static void genLabel (iCode *ic)
4169 {
4170   FENTRY;
4171
4172   /* special case never generate */
4173   if (IC_LABEL(ic) == entryLabel)
4174     return ;
4175
4176   pic16_emitpLabel(IC_LABEL(ic)->key);
4177 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4178 }
4179
4180 /*-----------------------------------------------------------------*/
4181 /* genGoto - generates a goto                                      */
4182 /*-----------------------------------------------------------------*/
4183 //tsd
4184 static void genGoto (iCode *ic)
4185 {
4186   FENTRY;
4187   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4188 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4189 }
4190
4191
4192 /*-----------------------------------------------------------------*/
4193 /* genMultbits :- multiplication of bits                           */
4194 /*-----------------------------------------------------------------*/
4195 static void genMultbits (operand *left, 
4196                          operand *right, 
4197                          operand *result)
4198 {
4199   FENTRY;
4200
4201   if(!pic16_sameRegs(AOP(result),AOP(right)))
4202     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4203
4204   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4205   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4206   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4207
4208 }
4209
4210
4211 /*-----------------------------------------------------------------*/
4212 /* genMultOneByte : 8 bit multiplication & division                */
4213 /*-----------------------------------------------------------------*/
4214 static void genMultOneByte (operand *left,
4215                             operand *right,
4216                             operand *result)
4217 {
4218
4219   FENTRY;
4220   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4221   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4222
4223   /* (if two literals, the value is computed before) */
4224   /* if one literal, literal on the right */
4225   if (AOP_TYPE(left) == AOP_LIT){
4226     operand *t = right;
4227     right = left;
4228     left = t;
4229   }
4230
4231         /* size is already checked in genMult == 1 */
4232 //      size = AOP_SIZE(result);
4233
4234         if (AOP_TYPE(right) == AOP_LIT){
4235                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4236                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4237                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4238                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4239         } else {
4240                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4241                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4242                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4243                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4244         }
4245         
4246         pic16_genMult8X8_n (left, right,result);
4247 }
4248
4249 #if 0
4250 /*-----------------------------------------------------------------*/
4251 /* genMultOneWord : 16 bit multiplication                          */
4252 /*-----------------------------------------------------------------*/
4253 static void genMultOneWord (operand *left,
4254                             operand *right,
4255                             operand *result)
4256 {
4257   FENTRY;
4258   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4259   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4260
4261   /* (if two literals, the value is computed before)
4262    * if one literal, literal on the right */
4263   if (AOP_TYPE(left) == AOP_LIT){
4264     operand *t = right;
4265     right = left;
4266     left = t;
4267   }
4268
4269   /* size is checked already == 2 */
4270 //  size = AOP_SIZE(result);
4271
4272   if (AOP_TYPE(right) == AOP_LIT) {
4273     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4274       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4275       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4276       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4277   } else {
4278     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4279       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4280       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4281       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4282   }
4283         
4284   pic16_genMult16X16_16(left, right,result);
4285 }
4286 #endif
4287
4288 #if 0
4289 /*-----------------------------------------------------------------*/
4290 /* genMultOneLong : 32 bit multiplication                          */
4291 /*-----------------------------------------------------------------*/
4292 static void genMultOneLong (operand *left,
4293                             operand *right,
4294                             operand *result)
4295 {
4296   FENTRY;
4297   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4298   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4299
4300   /* (if two literals, the value is computed before)
4301    * if one literal, literal on the right */
4302   if (AOP_TYPE(left) == AOP_LIT){
4303     operand *t = right;
4304     right = left;
4305     left = t;
4306   }
4307
4308   /* size is checked already == 4 */
4309 //  size = AOP_SIZE(result);
4310
4311   if (AOP_TYPE(right) == AOP_LIT) {
4312     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4313         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4314         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4315         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4316   } else {
4317     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4318         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4319         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4320         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4321   }
4322         
4323   pic16_genMult32X32_32(left, right,result);
4324 }
4325 #endif
4326
4327
4328
4329 /*-----------------------------------------------------------------*/
4330 /* genMult - generates code for multiplication                     */
4331 /*-----------------------------------------------------------------*/
4332 static void genMult (iCode *ic)
4333 {
4334   operand *left = IC_LEFT(ic);
4335   operand *right = IC_RIGHT(ic);
4336   operand *result= IC_RESULT(ic);   
4337
4338     FENTRY;
4339         /* assign the amsops */
4340         pic16_aopOp (left,ic,FALSE);
4341         pic16_aopOp (right,ic,FALSE);
4342         pic16_aopOp (result,ic,TRUE);
4343
4344         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4345
4346         /* special cases first *
4347         * both are bits */
4348         if (AOP_TYPE(left) == AOP_CRY
4349                 && AOP_TYPE(right)== AOP_CRY) {
4350                 genMultbits(left,right,result);
4351           goto release ;
4352         }
4353
4354         /* if both are of size == 1 */
4355         if(AOP_SIZE(left) == 1
4356                 && AOP_SIZE(right) == 1) {
4357                 genMultOneByte(left,right,result);
4358           goto release ;
4359         }
4360
4361 #if 0
4362         /* if both are of size == 2 */
4363         if(AOP_SIZE(left) == 2
4364                 && AOP_SIZE(right) == 2) {
4365                 genMultOneWord(left, right, result);
4366           goto release;
4367         }
4368         
4369         /* if both are of size == 4 */
4370         if(AOP_SIZE(left) == 4
4371                 && AOP_SIZE(right) == 4) {
4372                 genMultOneLong(left, right, result);
4373           goto release;
4374         }
4375 #endif
4376
4377         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4378         assert( !"Multiplication should have been transformed into function call!" );
4379
4380         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4381
4382
4383         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4384         /* should have been converted to function call */
4385         assert(0) ;
4386
4387 release :
4388         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4389         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4390         pic16_freeAsmop(result,NULL,ic,TRUE); 
4391 }
4392
4393 #if 0
4394 /*-----------------------------------------------------------------*/
4395 /* genDivbits :- division of bits                                  */
4396 /*-----------------------------------------------------------------*/
4397 static void genDivbits (operand *left, 
4398                         operand *right, 
4399                         operand *result)
4400 {
4401   char *l;
4402
4403     FENTRY;
4404     /* the result must be bit */    
4405     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4406     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4407
4408     MOVA(l);    
4409
4410     pic16_emitcode("div","ab");
4411     pic16_emitcode("rrc","a");
4412     pic16_aopPut(AOP(result),"c",0);
4413 }
4414
4415 /*-----------------------------------------------------------------*/
4416 /* genDivOneByte : 8 bit division                                  */
4417 /*-----------------------------------------------------------------*/
4418 static void genDivOneByte (operand *left,
4419                            operand *right,
4420                            operand *result)
4421 {
4422   sym_link *opetype = operandType(result);
4423   char *l ;
4424   symbol *lbl ;
4425   int size,offset;
4426
4427         /* result = divident / divisor
4428          * - divident may be a register or a literal,
4429          * - divisor may be a register or a literal,
4430          * so there are 3 cases (literal / literal is optimized
4431          * by the front-end) to handle.
4432          * In addition we must handle signed and unsigned, which
4433          * result in 6 final different cases -- VR */
4434
4435     FENTRY;
4436     
4437     size = AOP_SIZE(result) - 1;
4438     offset = 1;
4439     /* signed or unsigned */
4440     if (SPEC_USIGN(opetype)) {
4441       pCodeOp *pct1,    /* count */
4442                 *pct2,  /* reste */
4443                 *pct3;  /* temp */
4444       symbol *label1, *label2, *label3;;
4445
4446
4447         /* unsigned is easy */
4448
4449         pct1 = pic16_popGetTempReg(1);
4450         pct2 = pic16_popGetTempReg(1);
4451         pct3 = pic16_popGetTempReg(1);
4452         
4453         label1 = newiTempLabel(NULL);
4454         label2 = newiTempLabel(NULL);
4455         label3 = newiTempLabel(NULL);
4456
4457         /* the following algorithm is extracted from divuint.c */
4458
4459         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4460         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4461         
4462         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4463
4464         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4465         
4466         pic16_emitpLabel(label1->key);
4467         
4468         emitCLRC;
4469         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4470
4471
4472         emitCLRC;
4473         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4474         
4475
4476         emitSKPNC;
4477         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4478         
4479         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4480         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4481         
4482         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4483         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4484         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4485         
4486         pic16_emitpLabel( label3->key );
4487         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4488         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4489         
4490         
4491
4492         pic16_emitpLabel(label2->key);
4493         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4494         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4495         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4496         
4497         /* result is in wreg */
4498         if(AOP_TYPE(result) != AOP_ACC)
4499                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4500
4501         pic16_popReleaseTempReg( pct3, 1);
4502         pic16_popReleaseTempReg( pct2, 1);
4503         pic16_popReleaseTempReg( pct1, 1);
4504
4505         return ;
4506     }
4507
4508     /* signed is a little bit more difficult */
4509
4510     /* save the signs of the operands */
4511     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4512     MOVA(l);    
4513     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4514     pic16_emitcode("push","acc"); /* save it on the stack */
4515
4516     /* now sign adjust for both left & right */
4517     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4518     MOVA(l);       
4519     lbl = newiTempLabel(NULL);
4520     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4521     pic16_emitcode("cpl","a");   
4522     pic16_emitcode("inc","a");
4523     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4524     pic16_emitcode("mov","b,a");
4525
4526     /* sign adjust left side */
4527     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4528     MOVA(l);
4529
4530     lbl = newiTempLabel(NULL);
4531     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4532     pic16_emitcode("cpl","a");
4533     pic16_emitcode("inc","a");
4534     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4535
4536     /* now the division */
4537     pic16_emitcode("div","ab");
4538     /* we are interested in the lower order
4539     only */
4540     pic16_emitcode("mov","b,a");
4541     lbl = newiTempLabel(NULL);
4542     pic16_emitcode("pop","acc");   
4543     /* if there was an over flow we don't 
4544     adjust the sign of the result */
4545     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4546     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4547     CLRC;
4548     pic16_emitcode("clr","a");
4549     pic16_emitcode("subb","a,b");
4550     pic16_emitcode("mov","b,a");
4551     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4552
4553     /* now we are done */
4554     pic16_aopPut(AOP(result),"b",0);
4555     if(size > 0){
4556         pic16_emitcode("mov","c,b.7");
4557         pic16_emitcode("subb","a,acc");   
4558     }
4559     while (size--)
4560         pic16_aopPut(AOP(result),"a",offset++);
4561
4562 }
4563 #endif
4564
4565 /*-----------------------------------------------------------------*/
4566 /* genDiv - generates code for division                            */
4567 /*-----------------------------------------------------------------*/
4568 static void genDiv (iCode *ic)
4569 {
4570     operand *left = IC_LEFT(ic);
4571     operand *right = IC_RIGHT(ic);
4572     operand *result= IC_RESULT(ic);   
4573     int negated = 0;
4574     int leftVal = 0, rightVal = 0;
4575     int signedLits = 0;
4576     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4577     int op = 0;
4578     
4579         /* Division is a very lengthy algorithm, so it is better
4580          * to call support routines than inlining algorithm.
4581          * Division functions written here just in case someone
4582          * wants to inline and not use the support libraries -- VR */
4583
4584     FENTRY;
4585     
4586     /* assign the amsops */
4587     pic16_aopOp (left,ic,FALSE);
4588     pic16_aopOp (right,ic,FALSE);
4589     pic16_aopOp (result,ic,TRUE);
4590
4591     if (ic->op == '/')
4592       op = 0;
4593     else if (ic->op == '%')
4594       op = 1;
4595     else
4596       assert( !"invalid operation requested in genDivMod" );
4597
4598     /* get literal values */
4599     if (IS_VALOP(left)) {
4600       leftVal = (int)floatFromVal( OP_VALUE(left) );
4601       assert( leftVal >= -128 && leftVal < 256 );
4602       if (leftVal < 0) { signedLits++; }
4603     }
4604     if (IS_VALOP(right)) {
4605       rightVal = (int)floatFromVal( OP_VALUE(right) );
4606       assert( rightVal >= -128 && rightVal < 256 );
4607       if (rightVal < 0) { signedLits++; }
4608     }
4609
4610     /* We should only come here to convert all
4611      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4612      * with exactly one operand being s8_t into
4613      * u8_t x u8_t -> u8_t. All other cases should have been
4614      * turned into calls to support routines beforehand... */
4615     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4616         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4617     {
4618       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4619           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4620       {
4621         /* Both operands are signed or negative, use _divschar
4622          * instead of _divuchar */
4623         pushaop(AOP(right), 0);
4624         pushaop(AOP(left), 0);
4625
4626         /* call _divschar */
4627         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4628
4629         {
4630           symbol *sym;
4631           sym = newSymbol( functions[op][0], 0 );
4632           sym->used++;
4633           strcpy(sym->rname, functions[op][0]);
4634           checkAddSym(&externs, sym);
4635         }
4636
4637         /* assign result */
4638         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4639         if (AOP_SIZE(result) > 1)
4640         {
4641           pic16_emitpcode(POC_MOVFF,
4642               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4643                 pic16_popGet(AOP(result), 1)));
4644           /* sign extend */
4645           pic16_addSign(result, 2, 1);
4646         }
4647
4648         /* clean up stack */
4649         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4650         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4651
4652         goto release;
4653       }
4654       
4655       /* push right operand */
4656       if (IS_VALOP(right)) {
4657         if (rightVal < 0) {
4658           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4659           negated++;
4660         } else {
4661           pushaop(AOP(right), 0);
4662         }
4663       } else if (!IS_UNSIGNED(operandType(right))) {
4664         pic16_mov2w(AOP(right), 0);
4665         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4666         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4667         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4668         negated++;
4669       } else {
4670         pushaop(AOP(right), 0);
4671       }
4672
4673       /* push left operand */
4674       if (IS_VALOP(left)) {
4675         if (leftVal < 0) {
4676           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4677           negated++;
4678         } else {
4679           pushaop(AOP(left), 0);
4680         }
4681       } else if (!IS_UNSIGNED(operandType(left))) {
4682         pic16_mov2w(AOP(left),0);
4683         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4684         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4685         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4686         negated++;
4687       } else {
4688         pushaop(AOP(left), 0);
4689       }
4690       
4691       /* call _divuchar */
4692       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4693
4694       {
4695         symbol *sym;
4696         sym = newSymbol( functions[op][1], 0 );
4697         sym->used++;
4698         strcpy(sym->rname, functions[op][1]);
4699         checkAddSym(&externs, sym);
4700       }
4701
4702       /* Revert negation(s) from above.
4703        * This is inefficient: if both operands are negative, this
4704        * should not touch WREG. However, determining that exactly
4705        * one operand was negated costs at least 3 instructions,
4706        * so there is nothing to be gained here, is there?
4707        *
4708        * I negate WREG because either operand might share registers with
4709        * result, so assigning first might destroy an operand. */
4710       
4711       /* For the modulus operator, (a/b)*b == a shall hold.
4712        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4713        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
4714        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
4715        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
4716        * Only invert the result if the left operand is negative (sigh).
4717        */
4718       if (AOP_SIZE(result) <= 1 || !negated)
4719       {
4720         if (ic->op == '/')
4721         {
4722           if (IS_VALOP(right)) {
4723             if (rightVal < 0) {
4724               /* we negated this operand above */
4725               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4726             }
4727           } else if (!IS_UNSIGNED(operandType(right))) {
4728             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4729             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4730           }
4731         }
4732
4733         if (IS_VALOP(left)) {
4734           if (leftVal < 0) {
4735             /* we negated this operand above */
4736             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4737           }
4738         } else if (!IS_UNSIGNED(operandType(left))) {
4739           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4740           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4741         }
4742
4743         /* Move result to destination. */
4744         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4745
4746         /* Zero-extend:  no operand was signed (or result is just a byte). */
4747         pic16_addSign(result, 1, 0);
4748       } else {
4749         assert( AOP_SIZE(result) > 1 );
4750         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4751         if (ic->op == '/')
4752         {
4753           if (IS_VALOP(right)) {
4754             if (rightVal < 0) {
4755               /* we negated this operand above */
4756               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4757             }
4758           } else if (!IS_UNSIGNED(operandType(right))) {
4759             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4760             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4761           }
4762         }
4763
4764         if (IS_VALOP(left)) {
4765           if (leftVal < 0) {
4766             /* we negated this operand above */
4767             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4768           }
4769         } else if (!IS_UNSIGNED(operandType(left))) {
4770           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4771           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4772         }
4773
4774         /* Move result to destination. */
4775         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4776
4777         /* Negate result if required. */
4778         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4779         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4780
4781         /* Sign-extend. */
4782         pic16_addSign(result, 2, 1);
4783       }
4784
4785       /* clean up stack */
4786       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4787       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4788       goto release;
4789     }
4790
4791 #if 0
4792     /* special cases first */
4793     /* both are bits */
4794     if (AOP_TYPE(left) == AOP_CRY &&
4795         AOP_TYPE(right)== AOP_CRY) {
4796         genDivbits(left,right,result);
4797         goto release ;
4798     }
4799
4800     /* if both are of size == 1 */
4801     if (AOP_SIZE(left) == 1 &&
4802         AOP_SIZE(right) == 1 ) {
4803         genDivOneByte(left,right,result);
4804         goto release ;
4805     }
4806 #endif
4807
4808     /* should have been converted to function call */
4809     assert(0);
4810 release :
4811     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4812     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4813     pic16_freeAsmop(result,NULL,ic,TRUE); 
4814 }
4815
4816 #if 0
4817 /*-----------------------------------------------------------------*/
4818 /* genModbits :- modulus of bits                                   */
4819 /*-----------------------------------------------------------------*/
4820 static void genModbits (operand *left, 
4821                         operand *right, 
4822                         operand *result)
4823 {
4824   char *l;
4825
4826     FENTRY;  
4827     
4828     werror(W_POSSBUG2, __FILE__, __LINE__);
4829     /* the result must be bit */    
4830     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4831     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4832
4833     MOVA(l);       
4834
4835     pic16_emitcode("div","ab");
4836     pic16_emitcode("mov","a,b");
4837     pic16_emitcode("rrc","a");
4838     pic16_aopPut(AOP(result),"c",0);
4839 }
4840
4841 /*-----------------------------------------------------------------*/
4842 /* genModOneByte : 8 bit modulus                                   */
4843 /*-----------------------------------------------------------------*/
4844 static void genModOneByte (operand *left,
4845                            operand *right,
4846                            operand *result)
4847 {
4848   sym_link *opetype = operandType(result);
4849   char *l ;
4850   symbol *lbl ;
4851
4852     FENTRY;
4853     werror(W_POSSBUG2, __FILE__, __LINE__);
4854
4855     /* signed or unsigned */
4856     if (SPEC_USIGN(opetype)) {
4857         /* unsigned is easy */
4858         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4859         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4860         MOVA(l);    
4861         pic16_emitcode("div","ab");
4862         pic16_aopPut(AOP(result),"b",0);
4863         return ;
4864     }
4865
4866     /* signed is a little bit more difficult */
4867
4868     /* save the signs of the operands */
4869     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4870     MOVA(l);
4871
4872     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4873     pic16_emitcode("push","acc"); /* save it on the stack */
4874
4875     /* now sign adjust for both left & right */
4876     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4877     MOVA(l);
4878
4879     lbl = newiTempLabel(NULL);
4880     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4881     pic16_emitcode("cpl","a");   
4882     pic16_emitcode("inc","a");
4883     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4884     pic16_emitcode("mov","b,a"); 
4885
4886     /* sign adjust left side */
4887     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4888     MOVA(l);
4889
4890     lbl = newiTempLabel(NULL);
4891     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4892     pic16_emitcode("cpl","a");   
4893     pic16_emitcode("inc","a");
4894     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4895
4896     /* now the multiplication */
4897     pic16_emitcode("div","ab");
4898     /* we are interested in the lower order
4899     only */
4900     lbl = newiTempLabel(NULL);
4901     pic16_emitcode("pop","acc");   
4902     /* if there was an over flow we don't 
4903     adjust the sign of the result */
4904     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4905     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4906     CLRC ;
4907     pic16_emitcode("clr","a");
4908     pic16_emitcode("subb","a,b");
4909     pic16_emitcode("mov","b,a");
4910     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4911
4912     /* now we are done */
4913     pic16_aopPut(AOP(result),"b",0);
4914
4915 }
4916 #endif
4917
4918 /*-----------------------------------------------------------------*/
4919 /* genMod - generates code for division                            */
4920 /*-----------------------------------------------------------------*/
4921 static void genMod (iCode *ic)
4922 {
4923   /* Task deferred to genDiv */
4924   genDiv(ic);
4925 #if 0
4926   operand *left = IC_LEFT(ic);
4927   operand *right = IC_RIGHT(ic);
4928   operand *result= IC_RESULT(ic);  
4929
4930     FENTRY;
4931     
4932     /* assign the amsops */
4933     pic16_aopOp (left,ic,FALSE);
4934     pic16_aopOp (right,ic,FALSE);
4935     pic16_aopOp (result,ic,TRUE);
4936
4937     /* special cases first */
4938     /* both are bits */
4939     if (AOP_TYPE(left) == AOP_CRY &&
4940         AOP_TYPE(right)== AOP_CRY) {
4941         genModbits(left,right,result);
4942         goto release ;
4943     }
4944
4945     /* if both are of size == 1 */
4946     if (AOP_SIZE(left) == 1 &&
4947         AOP_SIZE(right) == 1 ) {
4948         genModOneByte(left,right,result);
4949         goto release ;
4950     }
4951
4952     /* should have been converted to function call */
4953     assert(0);
4954
4955 release :
4956     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4957     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4958     pic16_freeAsmop(result,NULL,ic,TRUE); 
4959 #endif
4960 }
4961
4962 /*-----------------------------------------------------------------*/
4963 /* genIfxJump :- will create a jump depending on the ifx           */
4964 /*-----------------------------------------------------------------*/
4965 /*
4966   note: May need to add parameter to indicate when a variable is in bit space.
4967 */
4968 static void genIfxJump (iCode *ic, char *jval)
4969 {
4970   FENTRY;
4971   
4972     /* if true label then we jump if condition
4973     supplied is true */
4974     if ( IC_TRUE(ic) ) {
4975
4976         if(strcmp(jval,"a") == 0)
4977           emitSKPZ;
4978         else if (strcmp(jval,"c") == 0)
4979           emitSKPNC;
4980         else {
4981           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4982           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4983         }
4984
4985         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4986         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4987
4988     }
4989     else {
4990         /* false label is present */
4991         if(strcmp(jval,"a") == 0)
4992           emitSKPNZ;
4993         else if (strcmp(jval,"c") == 0)
4994           emitSKPC;
4995         else {
4996           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4997           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4998         }
4999
5000         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5001         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5002
5003     }
5004
5005
5006     /* mark the icode as generated */
5007     ic->generated = 1;
5008 }
5009
5010 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5011 {
5012   FENTRY;
5013   
5014     /* if true label then we jump if condition
5015     supplied is true */
5016     if ( IC_TRUE(ic) ) {
5017       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
5018       pic16_emitpcode(POC_BTFSC, jop);
5019
5020       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5021       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5022
5023     } else {
5024       /* false label is present */
5025       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5026       pic16_emitpcode(POC_BTFSS, jop);
5027           
5028       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5029       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5030     }
5031
5032
5033     /* mark the icode as generated */
5034     ic->generated = 1;
5035 }
5036
5037 #if 0
5038 // not needed ATM
5039
5040 /*-----------------------------------------------------------------*/
5041 /* genSkip                                                         */
5042 /*-----------------------------------------------------------------*/
5043 static void genSkip(iCode *ifx,int status_bit)
5044 {
5045   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5046   if(!ifx)
5047     return;
5048
5049   if ( IC_TRUE(ifx) ) {
5050     switch(status_bit) {
5051     case 'z':
5052       emitSKPNZ;
5053       break;
5054
5055     case 'c':
5056       emitSKPNC;
5057       break;
5058
5059     case 'd':
5060       emitSKPDC;
5061       break;
5062
5063     }
5064
5065     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5066     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5067
5068   } else {
5069
5070     switch(status_bit) {
5071
5072     case 'z':
5073       emitSKPZ;
5074       break;
5075
5076     case 'c':
5077       emitSKPC;
5078       break;
5079
5080     case 'd':
5081       emitSKPDC;
5082       break;
5083     }
5084     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5085     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5086
5087   }
5088
5089 }
5090 #endif
5091
5092 /*-----------------------------------------------------------------*/
5093 /* genSkipc                                                        */
5094 /*-----------------------------------------------------------------*/
5095 static void genSkipc(resolvedIfx *rifx)
5096 {
5097   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5098   
5099   if(!rifx)
5100     return;
5101
5102   if(rifx->condition)
5103     emitSKPNC;
5104   else
5105     emitSKPC;
5106
5107   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5108   rifx->generated = 1;
5109 }
5110
5111 #if !(USE_SIMPLE_GENCMP)
5112 /*-----------------------------------------------------------------*/
5113 /* genSkipz2                                                       */
5114 /*-----------------------------------------------------------------*/
5115 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5116 {
5117   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5118   
5119   if(!rifx)
5120     return;
5121
5122   if( (rifx->condition ^ invert_condition) & 1)
5123     emitSKPZ;
5124   else
5125     emitSKPNZ;
5126
5127   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5128   rifx->generated = 1;
5129 }
5130 #endif
5131
5132 #if 0
5133 /*-----------------------------------------------------------------*/
5134 /* genSkipz                                                        */
5135 /*-----------------------------------------------------------------*/
5136 static void genSkipz(iCode *ifx, int condition)
5137 {
5138   if(!ifx)
5139     return;
5140
5141   if(condition)
5142     emitSKPNZ;
5143   else
5144     emitSKPZ;
5145
5146   if ( IC_TRUE(ifx) )
5147     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5148   else
5149     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5150
5151   if ( IC_TRUE(ifx) )
5152     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5153   else
5154     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5155
5156 }
5157 #endif
5158
5159 #if !(USE_SIMPLE_GENCMP)
5160 /*-----------------------------------------------------------------*/
5161 /* genSkipCond                                                     */
5162 /*-----------------------------------------------------------------*/
5163 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5164 {
5165   if(!rifx)
5166     return;
5167
5168   if(rifx->condition)
5169     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5170   else
5171     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5172
5173
5174   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5175   rifx->generated = 1;
5176 }
5177 #endif
5178
5179 #if 0
5180 /*-----------------------------------------------------------------*/
5181 /* genChkZeroes :- greater or less than comparison                 */
5182 /*     For each byte in a literal that is zero, inclusive or the   */
5183 /*     the corresponding byte in the operand with W                */
5184 /*     returns true if any of the bytes are zero                   */
5185 /*-----------------------------------------------------------------*/
5186 static int genChkZeroes(operand *op, int lit,  int size)
5187 {
5188
5189   int i;
5190   int flag =1;
5191
5192   while(size--) {
5193     i = (lit >> (size*8)) & 0xff;
5194
5195     if(i==0) {
5196       if(flag) 
5197         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5198       else
5199         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5200       flag = 0;
5201     }
5202   }
5203
5204   return (flag==0);
5205 }
5206 #endif
5207
5208
5209 /*-----------------------------------------------------------------*/
5210 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
5211 /*                  aop (if it's NOT a literal) or from lit (if    */
5212 /*                  aop is a literal)                              */
5213 /*-----------------------------------------------------------------*/
5214 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5215   if (aop->type == AOP_LIT) {
5216     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5217   } else {
5218     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5219   }
5220 }
5221
5222 /*-----------------------------------------------------------------*/
5223 /* genCmp :- greater or less than comparison                       */
5224 /*-----------------------------------------------------------------*/
5225
5226 #if USE_SIMPLE_GENCMP           /* { */
5227
5228 /* genCmp performs a left < right comparison, stores
5229  * the outcome in result (if != NULL) and generates
5230  * control flow code for the ifx (if != NULL).
5231  *
5232  * This version leaves in sequences like
5233  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5234  * which should be optmized by the peephole
5235  * optimizer - RN 2005-01-01 */
5236 static void genCmp (operand *left,operand *right,
5237                     operand *result, iCode *ifx, int sign)
5238 {
5239   resolvedIfx rIfx;
5240   int size;
5241   int offs;
5242   symbol *templbl;
5243   operand *dummy;
5244   unsigned long lit;
5245   unsigned long mask;
5246   int performedLt;
5247
5248   FENTRY;
5249   
5250   assert (left && right);
5251   assert (AOP_SIZE(left) == AOP_SIZE(right));
5252
5253   size = AOP_SIZE(right) - 1;
5254   mask = (0x100UL << (size*8)) - 1;
5255   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5256   performedLt = 1;
5257   templbl = NULL;
5258   lit = 0;
5259   
5260   resolveIfx (&rIfx, ifx);
5261
5262   /* handle for special cases */
5263   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5264       return;
5265
5266   /**********************************************************************
5267    * handle bits - bit compares are promoted to int compares seemingly! *
5268    **********************************************************************/
5269 #if 0
5270   // THIS IS COMPLETELY UNTESTED!
5271   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5272     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5273     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5274     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5275
5276     emitSETC;
5277     // 1 < {0,1} is false --> clear C by skipping the next instruction
5278     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5279     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5280     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5281     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5282     emitCLRC; // only skipped for left=0 && right=1
5283
5284     goto correct_result_in_carry;
5285   } // if
5286 #endif
5287
5288   /*************************************************
5289    * make sure that left is register (or the like) *
5290    *************************************************/
5291   if (!isAOP_REGlike(left)) {
5292     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5293     assert (isAOP_LIT(left));
5294     assert (isAOP_REGlike(right));
5295     // swap left and right
5296     // left < right <==> right > left <==> (right >= left + 1)
5297     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5298
5299     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5300       // MAXVALUE < right? always false
5301       if (performedLt) emitCLRC; else emitSETC;
5302       goto correct_result_in_carry;
5303     } // if
5304
5305     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5306     // that's why we handled it above.
5307     lit++;
5308
5309     dummy = left;
5310     left = right;
5311     right = dummy;
5312
5313     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5314   } else if (isAOP_LIT(right)) {
5315     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5316   } // if
5317
5318   assert (isAOP_REGlike(left)); // left must be register or the like
5319   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5320
5321   /*************************************************
5322    * special cases go here                         *
5323    *************************************************/
5324
5325   if (isAOP_LIT(right)) {
5326     if (!sign) {
5327       // unsigned comparison to a literal
5328       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5329       if (lit == 0) {
5330         // unsigned left < 0? always false
5331         if (performedLt) emitCLRC; else emitSETC;
5332         goto correct_result_in_carry;
5333       }
5334     } else {
5335       // signed comparison to a literal
5336       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5337       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5338         // signed left < 0x80000000? always false
5339         if (performedLt) emitCLRC; else emitSETC;
5340         goto correct_result_in_carry;
5341       } else if (lit == 0) {
5342         // compare left < 0; set CARRY if SIGNBIT(left) is set
5343         if (performedLt) emitSETC; else emitCLRC;
5344         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5345         if (performedLt) emitCLRC; else emitSETC;
5346         goto correct_result_in_carry;
5347       }
5348     } // if (!sign)
5349   } // right is literal
5350
5351   /*************************************************
5352    * perform a general case comparison             *
5353    * make sure we get CARRY==1 <==> left >= right  *
5354    *************************************************/
5355   // compare most significant bytes
5356   //DEBUGpc ("comparing bytes at offset %d", size);
5357   if (!sign) {
5358     // unsigned comparison
5359     mov2w_regOrLit (AOP(right), lit, size);
5360     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5361   } else {
5362     // signed comparison
5363     // (add 2^n to both operands then perform an unsigned comparison)
5364     if (isAOP_LIT(right)) {
5365       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5366       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5367
5368       if (litbyte == 0x80) {
5369         // left >= 0x80 -- always true, but more bytes to come
5370         pic16_mov2w (AOP(left), size);
5371         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5372         emitSETC;
5373       } else {
5374         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5375         pic16_mov2w (AOP(left), size);
5376         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5377         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5378       } // if
5379     } else {
5380       /* using PRODL as a temporary register here */
5381       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5382       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5383       pic16_mov2w (AOP(left), size);
5384       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5385       pic16_emitpcode (POC_MOVWF, pctemp);
5386       pic16_mov2w (AOP(right), size);
5387       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5388       pic16_emitpcode (POC_SUBFW, pctemp);
5389       //pic16_popReleaseTempReg(pctemp, 1);
5390     }
5391   } // if (!sign)
5392
5393   // compare remaining bytes (treat as unsigned case from above)
5394   templbl = newiTempLabel ( NULL );
5395   offs = size;
5396   while (offs--) {
5397     //DEBUGpc ("comparing bytes at offset %d", offs);
5398     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5399     mov2w_regOrLit (AOP(right), lit, offs);
5400     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5401   } // while (offs)
5402   pic16_emitpLabel (templbl->key);
5403   goto result_in_carry;
5404
5405 result_in_carry:
5406   
5407   /****************************************************
5408    * now CARRY contains the result of the comparison: *
5409    * SUBWF sets CARRY iff                             *
5410    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5411    * (F=left, W=right)                                *
5412    ****************************************************/
5413
5414   if (performedLt) {
5415     if (result && AOP_TYPE(result) != AOP_CRY) {
5416       // value will be stored
5417       emitTOGC;
5418     } else {
5419       // value wil only be used in the following genSkipc()
5420       rIfx.condition ^= 1;
5421     }
5422   } // if
5423
5424 correct_result_in_carry:
5425
5426   // assign result to variable (if neccessary)
5427   if (result && AOP_TYPE(result) != AOP_CRY) {
5428     //DEBUGpc ("assign result");
5429     size = AOP_SIZE(result);
5430     while (size--) {
5431       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5432     } // while
5433     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5434   } // if (result)
5435
5436   // perform conditional jump
5437   if (ifx) {
5438     //DEBUGpc ("generate control flow");
5439     genSkipc (&rIfx);
5440     ifx->generated = 1;
5441   } // if
5442 }
5443
5444 #elif 1         /* } */
5445                 /* { */
5446       /* original code */
5447 static void genCmp (operand *left,operand *right,
5448                     operand *result, iCode *ifx, int sign)
5449 {
5450   int size; //, offset = 0 ;
5451   unsigned long lit = 0L,i = 0;
5452   resolvedIfx rFalseIfx;
5453   //  resolvedIfx rTrueIfx;
5454   symbol *truelbl;
5455   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5456 /*
5457   if(ifx) {
5458     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5459     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5460   }
5461 */
5462
5463   FENTRY;
5464   
5465   resolveIfx(&rFalseIfx,ifx);
5466   truelbl  = newiTempLabel(NULL);
5467   size = max(AOP_SIZE(left),AOP_SIZE(right));
5468
5469   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5470
5471 #define _swapp
5472
5473   /* if literal is on the right then swap with left */
5474   if ((AOP_TYPE(right) == AOP_LIT)) {
5475     operand *tmp = right ;
5476     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5477     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5478 #ifdef _swapp
5479
5480     lit = (lit - 1) & mask;
5481     right = left;
5482     left = tmp;
5483     rFalseIfx.condition ^= 1;
5484 #endif
5485
5486   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5487     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5488   }
5489
5490
5491   //if(IC_TRUE(ifx) == NULL)
5492   /* if left & right are bit variables */
5493   if (AOP_TYPE(left) == AOP_CRY &&
5494       AOP_TYPE(right) == AOP_CRY ) {
5495     assert (0 && "bit variables used in genCmp");
5496     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5497     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5498   } else {
5499     /* subtract right from left if at the
5500        end the carry flag is set then we know that
5501        left is greater than right */
5502
5503     symbol *lbl  = newiTempLabel(NULL);
5504
5505 #if 0
5506         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5507                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5508 #endif
5509
5510 #ifndef _swapp
5511     if(AOP_TYPE(right) == AOP_LIT) {
5512
5513       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5514
5515       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5516
5517       /* special cases */
5518
5519       if(lit == 0) {
5520
5521         if(sign != 0) 
5522           genSkipCond(&rFalseIfx,left,size-1,7);
5523         else 
5524           /* no need to compare to 0...*/
5525           /* NOTE: this is a de-generate compare that most certainly 
5526            *       creates some dead code. */
5527           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5528
5529         if(ifx) ifx->generated = 1;
5530         return;
5531
5532       }
5533       size--;
5534
5535       if(size == 0) {
5536         //i = (lit >> (size*8)) & 0xff;
5537         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5538         
5539         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5540
5541         i = ((0-lit) & 0xff);
5542         if(sign) {
5543           if( i == 0x81) { 
5544             /* lit is 0x7f, all signed chars are less than
5545              * this except for 0x7f itself */
5546             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5547             genSkipz2(&rFalseIfx,0);
5548           } else {
5549             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5550             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5551             genSkipc(&rFalseIfx);
5552           }
5553
5554         } else {
5555           if(lit == 1) {
5556             genSkipz2(&rFalseIfx,1);
5557           } else {
5558             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5559             genSkipc(&rFalseIfx);
5560           }
5561         }
5562
5563         if(ifx) ifx->generated = 1;
5564         return;
5565       }
5566
5567       /* chars are out of the way. now do ints and longs */
5568
5569
5570       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5571         
5572       /* special cases */
5573
5574       if(sign) {
5575
5576         if(lit == 0) {
5577           genSkipCond(&rFalseIfx,left,size,7);
5578           if(ifx) ifx->generated = 1;
5579           return;
5580         }
5581
5582         if(lit <0x100) {
5583           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5584
5585           //rFalseIfx.condition ^= 1;
5586           //genSkipCond(&rFalseIfx,left,size,7);
5587           //rFalseIfx.condition ^= 1;
5588
5589           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5590           if(rFalseIfx.condition)
5591             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5592           else
5593             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5594
5595           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5596           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5597           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5598
5599           while(size > 1)
5600             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5601
5602           if(rFalseIfx.condition) {
5603             emitSKPZ;
5604             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5605
5606           } else {
5607             emitSKPNZ;
5608           }
5609
5610           genSkipc(&rFalseIfx);
5611           pic16_emitpLabel(truelbl->key);
5612           if(ifx) ifx->generated = 1;
5613           return;
5614
5615         }
5616
5617         if(size == 1) {
5618
5619           if( (lit & 0xff) == 0) {
5620             /* lower byte is zero */
5621             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5622             i = ((lit >> 8) & 0xff) ^0x80;
5623             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5624             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5625             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5626             genSkipc(&rFalseIfx);
5627
5628
5629             if(ifx) ifx->generated = 1;
5630             return;
5631
5632           }
5633         } else {
5634           /* Special cases for signed longs */
5635           if( (lit & 0xffffff) == 0) {
5636             /* lower byte is zero */
5637             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5638             i = ((lit >> 8*3) & 0xff) ^0x80;
5639             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5640             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5641             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5642             genSkipc(&rFalseIfx);
5643
5644
5645             if(ifx) ifx->generated = 1;
5646             return;
5647
5648           }
5649
5650         }
5651
5652
5653         if(lit & (0x80 << (size*8))) {
5654           /* lit is negative */
5655           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5656
5657           //genSkipCond(&rFalseIfx,left,size,7);
5658
5659           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5660
5661           if(rFalseIfx.condition)
5662             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5663           else
5664             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5665
5666
5667         } else {
5668           /* lit is positive */
5669           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5670           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5671           if(rFalseIfx.condition)
5672             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5673           else
5674             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5675
5676         }
5677
5678         /*
5679           This works, but is only good for ints.
5680           It also requires a "known zero" register.
5681           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5682           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5683           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5684           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5685           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5686           genSkipc(&rFalseIfx);
5687
5688           pic16_emitpLabel(truelbl->key);
5689           if(ifx) ifx->generated = 1;
5690           return;
5691         **/
5692           
5693         /* There are no more special cases, so perform a general compare */
5694   
5695         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5696         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5697
5698         while(size--) {
5699
5700           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5701           emitSKPNZ;
5702           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5703         }
5704         //rFalseIfx.condition ^= 1;
5705         genSkipc(&rFalseIfx);
5706
5707         pic16_emitpLabel(truelbl->key);
5708
5709         if(ifx) ifx->generated = 1;
5710         return;
5711
5712
5713       }
5714
5715
5716       /* sign is out of the way. So now do an unsigned compare */
5717       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5718
5719
5720       /* General case - compare to an unsigned literal on the right.*/
5721
5722       i = (lit >> (size*8)) & 0xff;
5723       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5724       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5725       while(size--) {
5726         i = (lit >> (size*8)) & 0xff;
5727
5728         if(i) {
5729           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5730           emitSKPNZ;
5731           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5732         } else {
5733           /* this byte of the lit is zero, 
5734            *if it's not the last then OR in the variable */
5735           if(size)
5736             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5737         }
5738       }
5739
5740
5741       pic16_emitpLabel(lbl->key);
5742 //      pic16_emitpLabel(truelbl->key);
5743       //if(emitFinalCheck)
5744       genSkipc(&rFalseIfx);
5745       if(sign)
5746         pic16_emitpLabel(truelbl->key);
5747
5748       if(ifx) ifx->generated = 1;
5749       return;
5750
5751
5752     }
5753 #endif  // _swapp
5754
5755     if(AOP_TYPE(left) == AOP_LIT) {
5756       //symbol *lbl = newiTempLabel(NULL);
5757
5758       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5759
5760
5761       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5762
5763       /* Special cases */
5764       if((lit == 0) && (sign == 0)){
5765
5766         size--;
5767         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5768         while(size) 
5769           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5770
5771         genSkipz2(&rFalseIfx,0);
5772         if(ifx) ifx->generated = 1;
5773         return;
5774       }
5775
5776       if(size==1) {
5777         /* Special cases */
5778         lit &= 0xff;
5779         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5780           /* degenerate compare can never be true */
5781           if(rFalseIfx.condition == 0)
5782             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5783
5784           if(ifx) ifx->generated = 1;
5785           return;
5786         }
5787
5788         if(sign) {
5789           /* signed comparisons to a literal byte */
5790
5791           int lp1 = (lit+1) & 0xff;
5792
5793           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5794           switch (lp1) {
5795           case 0:
5796             rFalseIfx.condition ^= 1;
5797             genSkipCond(&rFalseIfx,right,0,7);
5798             break;
5799           case 0x7f:
5800             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5801             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5802             genSkipz2(&rFalseIfx,1);
5803             break;
5804           default:
5805             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5806             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5807             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5808             rFalseIfx.condition ^= 1;
5809             genSkipc(&rFalseIfx);
5810             break;
5811           }
5812         } else {
5813           /* unsigned comparisons to a literal byte */
5814
5815           switch(lit & 0xff ) {
5816           case 0:
5817             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5818             genSkipz2(&rFalseIfx,0);
5819             break;
5820           case 0x7f:
5821             rFalseIfx.condition ^= 1;
5822             genSkipCond(&rFalseIfx,right,0,7);
5823             break;
5824
5825           default:
5826             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5827             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5828             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5829             rFalseIfx.condition ^= 1;
5830             if (AOP_TYPE(result) == AOP_CRY)
5831               genSkipc(&rFalseIfx);
5832             else {
5833               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5834               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5835             }         
5836             break;
5837           }
5838         }
5839
5840         if(ifx) ifx->generated = 1;
5841         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5842                 goto check_carry;
5843         return;
5844
5845       } else {
5846
5847         /* Size is greater than 1 */
5848
5849         if(sign) {
5850           int lp1 = lit+1;
5851
5852           size--;
5853
5854           if(lp1 == 0) {
5855             /* this means lit = 0xffffffff, or -1 */
5856
5857
5858             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5859             rFalseIfx.condition ^= 1;
5860             genSkipCond(&rFalseIfx,right,size,7);
5861             if(ifx) ifx->generated = 1;
5862
5863             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5864               goto check_carry;
5865
5866             return;
5867           }
5868
5869           if(lit == 0) {
5870             int s = size;
5871
5872             if(rFalseIfx.condition) {
5873               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5874               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5875             }
5876
5877             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5878             while(size--)
5879               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5880
5881
5882             emitSKPZ;
5883             if(rFalseIfx.condition) {
5884               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5885               pic16_emitpLabel(truelbl->key);
5886             }else {
5887               rFalseIfx.condition ^= 1;
5888               genSkipCond(&rFalseIfx,right,s,7);
5889             }
5890
5891             if(ifx) ifx->generated = 1;
5892
5893             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5894               goto check_carry;
5895
5896             return;
5897           }
5898
5899           if((size == 1) &&  (0 == (lp1&0xff))) {
5900             /* lower byte of signed word is zero */
5901             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5902             i = ((lp1 >> 8) & 0xff) ^0x80;
5903             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5904             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5905             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5906
5907             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5908               emitTOGC;
5909               if(ifx) ifx->generated = 1;
5910               goto check_carry;
5911             } else {
5912               rFalseIfx.condition ^= 1;
5913               genSkipc(&rFalseIfx);
5914               if(ifx) ifx->generated = 1;
5915             }
5916
5917             return;
5918           }
5919
5920           if(lit & (0x80 << (size*8))) {
5921             /* Lit is less than zero */
5922             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5923             //rFalseIfx.condition ^= 1;
5924             //genSkipCond(&rFalseIfx,left,size,7);
5925             //rFalseIfx.condition ^= 1;
5926             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5927             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5928
5929             if(rFalseIfx.condition)
5930               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5931             else
5932               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5933
5934
5935           } else {
5936             /* Lit is greater than or equal to zero */
5937             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5938             //rFalseIfx.condition ^= 1;
5939             //genSkipCond(&rFalseIfx,right,size,7);
5940             //rFalseIfx.condition ^= 1;
5941
5942             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5943             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5944
5945             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5946             if(rFalseIfx.condition)
5947               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5948             else
5949               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5950
5951           }
5952
5953           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5954           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5955
5956           while(size--) {
5957
5958             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5959             emitSKPNZ;
5960             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5961           }
5962           rFalseIfx.condition ^= 1;
5963           //rFalseIfx.condition = 1;
5964           genSkipc(&rFalseIfx);
5965
5966           pic16_emitpLabel(truelbl->key);
5967
5968           if(ifx) ifx->generated = 1;
5969
5970
5971           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5972             goto check_carry;
5973
5974           return;
5975           // end of if (sign)
5976         } else {
5977
5978           /* compare word or long to an unsigned literal on the right.*/
5979
5980
5981           size--;
5982           if(lit < 0xff) {
5983             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5984             switch (lit) {
5985             case 0:
5986               break; /* handled above */
5987 /*
5988             case 0xff:
5989               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5990               while(size--)
5991                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5992               genSkipz2(&rFalseIfx,0);
5993               break;
5994 */
5995             default:
5996               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5997               while(--size)
5998                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5999
6000               emitSKPZ;
6001               if(rFalseIfx.condition)
6002                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
6003               else
6004                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
6005
6006
6007               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6008               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6009
6010               rFalseIfx.condition ^= 1;
6011               genSkipc(&rFalseIfx);
6012             }
6013
6014             pic16_emitpLabel(truelbl->key);
6015
6016             if(ifx) ifx->generated = 1;
6017
6018             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6019               goto check_carry;
6020
6021             return;
6022           }
6023
6024
6025           lit++;
6026           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6027           i = (lit >> (size*8)) & 0xff;
6028
6029           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6030           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6031
6032           while(size--) {
6033             i = (lit >> (size*8)) & 0xff;
6034
6035             if(i) {
6036               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6037               emitSKPNZ;
6038               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6039             } else {
6040               /* this byte of the lit is zero, 
6041                * if it's not the last then OR in the variable */
6042               if(size)
6043                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6044             }
6045           }
6046
6047
6048           pic16_emitpLabel(lbl->key);
6049
6050           rFalseIfx.condition ^= 1;
6051
6052           genSkipc(&rFalseIfx);
6053         }
6054
6055         if(sign)
6056           pic16_emitpLabel(truelbl->key);
6057         if(ifx) ifx->generated = 1;
6058
6059             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6060               goto check_carry;
6061
6062         return;
6063       }
6064     }
6065     /* Compare two variables */
6066
6067     DEBUGpic16_emitcode(";sign","%d",sign);
6068
6069     size--;
6070     if(sign) {
6071       /* Sigh. thus sucks... */
6072       if(size) {
6073         pCodeOp *pctemp;
6074         
6075         pctemp = pic16_popGetTempReg(1);
6076         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6077         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6078         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6079         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6080         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6081         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6082         pic16_popReleaseTempReg(pctemp, 1);
6083       } else {
6084         /* Signed char comparison */
6085         /* Special thanks to Nikolai Golovchenko for this snippet */
6086         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6087         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6088         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6089         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6090         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6091         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6092
6093         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6094         genSkipc(&rFalseIfx);
6095           
6096         if(ifx) ifx->generated = 1;
6097
6098             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6099               goto check_carry;
6100
6101         return;
6102       }
6103
6104     } else {
6105
6106       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6107       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6108     }
6109
6110
6111     /* The rest of the bytes of a multi-byte compare */
6112     while (size) {
6113
6114       emitSKPZ;
6115       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6116       size--;
6117
6118       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6119       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6120
6121
6122     }
6123
6124     pic16_emitpLabel(lbl->key);
6125
6126     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6127     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6128         (AOP_TYPE(result) == AOP_REG)) {
6129       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6130       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6131     } else {
6132       genSkipc(&rFalseIfx);
6133     }         
6134     //genSkipc(&rFalseIfx);
6135     if(ifx) ifx->generated = 1;
6136
6137
6138             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6139               goto check_carry;
6140
6141     return;
6142
6143   }
6144
6145 check_carry:
6146   if ((AOP_TYPE(result) != AOP_CRY) 
6147         && AOP_SIZE(result)) {
6148     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6149
6150     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6151
6152     pic16_outBitC(result);
6153   } else {
6154     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6155     /* if the result is used in the next
6156        ifx conditional branch then generate
6157        code a little differently */
6158     if (ifx )
6159       genIfxJump (ifx,"c");
6160     else
6161       pic16_outBitC(result);
6162     /* leave the result in acc */
6163   }
6164
6165 }
6166
6167 #elif 0 /* VR version of genCmp() */    /* } else { */
6168
6169 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6170 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6171         operand *result, int offset, int invert_op)
6172 {
6173   /* add code here */
6174   
6175   /* check condition, > or < ?? */
6176   if(rIfx->condition != 0)invert_op ^= 1;
6177   
6178   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6179
6180   if(!ifx)invert_op ^= 1;
6181
6182   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6183       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6184   
6185   /* do selection */
6186   if(!invert_op)return POC_CPFSGT;
6187   else return POC_CPFSLT;
6188 }
6189
6190 static int compareAopfirstpass=1;
6191
6192 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6193             operand *oper, int offset, operand *result,
6194             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6195             symbol *tlbl)
6196 {
6197   int op;
6198   symbol *truelbl;
6199
6200   /* invert if there is a result to be loaded, in order to fit,
6201    * SETC/CLRC sequence */
6202   if(AOP_SIZE(result))invert_op ^= 1;
6203
6204 //  if(sign && !offset)invert_op ^= 1;
6205   
6206 //  if(sign)invert_op ^= 1;
6207   
6208   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6209
6210   if(AOP_SIZE(result) && compareAopfirstpass) {
6211     if(!ifx) {
6212       if(pcop2)
6213         pic16_emitpcode(POC_SETF, pcop2);
6214       else
6215         emitSETC;
6216     } else {
6217       if(pcop2)
6218         pic16_emitpcode(POC_CLRF, pcop2);
6219       else
6220         emitCLRC;
6221     }
6222   }
6223
6224   compareAopfirstpass = 0;
6225
6226       /* there is a bug when comparing operands with size > 1,
6227        * because higher bytes can be equal and test should be performed
6228        * to the next lower byte, current algorithm, considers operands
6229        * inequal in these cases! -- VR 20041107 */
6230
6231     
6232   if(pcop)
6233     pic16_emitpcode(op, pcop);
6234   else
6235     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6236
6237
6238   if((!sign || !offset) && AOP_SIZE(result)) {
6239     if(!ifx) {
6240       if(pcop2)
6241         pic16_emitpcode(POC_CLRF, pcop2);
6242         else
6243         emitCLRC;
6244     } else {
6245       if(pcop2)
6246         pic16_emitpcode(POC_SETF, pcop2);
6247       else
6248         emitSETC;
6249     }
6250     
6251     /* don't emit final branch (offset == 0) */
6252     if(offset) {
6253
6254       if(pcop2)
6255         pic16_emitpcode(POC_RRCF, pcop2);
6256
6257       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6258     }
6259   } else {
6260     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6261       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6262             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6263
6264       truelbl = newiTempLabel( NULL );
6265       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6266       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6267         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6268       else
6269         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6270       pic16_emitpLabel(truelbl->key);
6271     } else {
6272       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6273     }
6274   }
6275 }
6276
6277 static void genCmp (operand *left, operand *right,
6278                     operand *result, iCode *ifx, int sign)
6279 {
6280   int size, cmpop=1;
6281   long lit = 0L;
6282   resolvedIfx rFalseIfx;
6283   symbol *falselbl, *tlbl;
6284
6285     FENTRY;
6286     
6287     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6288
6289     resolveIfx(&rFalseIfx, ifx);
6290     size = max(AOP_SIZE(left), AOP_SIZE(right));
6291     
6292     /* if left & right are bit variables */
6293     if(AOP_TYPE(left) == AOP_CRY
6294       && AOP_TYPE(right) == AOP_CRY ) {
6295
6296         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6297         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6298         
6299         werror(W_POSSBUG2, __FILE__, __LINE__);
6300         exit(EXIT_FAILURE);
6301     }
6302     
6303     /* if literal is on the right then swap with left */
6304     if((AOP_TYPE(right) == AOP_LIT)) {
6305       operand *tmp = right ;
6306 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6307
6308         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6309
6310 //      lit = (lit - 1) & mask;
6311         right = left;
6312         left = tmp;
6313         rFalseIfx.condition ^= 1;               /* reverse compare */
6314     } else
6315     if ((AOP_TYPE(left) == AOP_LIT)) {
6316       /* float compares are handled by support functions */
6317       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6318     }
6319
6320     /* actual comparing algorithm */
6321 //    size = AOP_SIZE( right );
6322
6323     falselbl = newiTempLabel( NULL );
6324     if(AOP_TYPE(left) == AOP_LIT) {
6325       /* compare to literal */
6326       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6327       
6328       if(sign) {
6329         pCodeOp *pct, *pct2;
6330         symbol *tlbl1;
6331
6332         /* signed compare */
6333         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6334
6335         /* using PRODL:PRODH as a temporary register here */
6336         pct = pic16_popCopyReg(&pic16_pc_prodl);
6337         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6338         tlbl = newiTempLabel( NULL );
6339         
6340         /* first compare signs:
6341          *  a. if both are positive, compare just like unsigned
6342          *  b. if both are negative, invert cmpop, compare just like unsigned
6343          *  c. if different signs, determine the result directly */
6344
6345         size--;
6346
6347 #if 1
6348         /* { */
6349         tlbl1 = newiTempLabel( NULL );
6350 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6351
6352         if(lit > 0) {
6353
6354           /* literal is zero or positive:
6355            *  a. if carry is zero, too, continue compare,
6356            *  b. if carry is set, then continue depending on cmpop ^ condition:
6357            *    1. '<' return false (literal < variable),
6358            *    2. '>' return true (literal > variable) */
6359 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6360           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6361           
6362           
6363           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6364           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6365         } else 
6366         if(lit < 0) {
6367           
6368           /* literal is negative:
6369            *  a. if carry is set, too, continue compare,
6370            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6371            *    1. '<' return true (literal < variable),
6372            *    2. '>' return false (literal > variable) */
6373 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6374           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6375           
6376           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6377           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6378         }
6379 #if 1
6380         else {
6381           /* lit == 0 */
6382           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6383           
6384           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6385           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6386         }
6387 #endif
6388         
6389         
6390         pic16_emitpLabel( tlbl1->key );
6391 #endif  /* } */
6392
6393         compareAopfirstpass=1;
6394 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6395 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6396 //        pic16_emitpcode(POC_MOVWF, pct);
6397
6398 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6399         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6400 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6401         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6402
6403         /* generic case */        
6404           while( size-- ) {
6405 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6406 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6407 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6408 //            pic16_emitpcode(POC_MOVWF, pct);
6409
6410 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6411             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6412             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6413 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6414 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6415           }
6416         
6417         if(ifx)ifx->generated = 1;
6418
6419         if(AOP_SIZE(result)) {
6420           pic16_emitpLabel(tlbl->key);
6421           pic16_emitpLabel(falselbl->key);
6422           pic16_outBitOp( result, pct2 );
6423         } else {
6424           pic16_emitpLabel(tlbl->key);
6425         }
6426       } else {
6427
6428         /* unsigned compare */      
6429         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6430     
6431         compareAopfirstpass=1;
6432         while(size--) {
6433           
6434           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6435           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6436
6437         }
6438         if(ifx)ifx->generated = 1;
6439
6440         if(AOP_SIZE(result)) {
6441           pic16_emitpLabel(falselbl->key);
6442           pic16_outBitC( result );
6443         }
6444
6445       }
6446     } else {
6447       /* compare registers */
6448       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6449
6450
6451       if(sign) {
6452         pCodeOp *pct, *pct2;
6453         
6454         /* signed compare */
6455         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6456
6457         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6458         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6459         tlbl = newiTempLabel( NULL );
6460         
6461         compareAopfirstpass=1;
6462
6463         size--;
6464         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6465 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6466         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6467         pic16_emitpcode(POC_MOVWF, pct);
6468
6469         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6470 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6471         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6472
6473         /* WREG already holds left + 0x80 */
6474         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6475         
6476         while( size-- ) {
6477           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6478 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6479           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6480           pic16_emitpcode(POC_MOVWF, pct);
6481                 
6482           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6483 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6484           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6485
6486           /* WREG already holds left + 0x80 */
6487           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6488 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6489         }
6490         
6491         if(ifx)ifx->generated = 1;
6492
6493         if(AOP_SIZE(result)) {
6494           pic16_emitpLabel(tlbl->key);
6495           pic16_emitpLabel(falselbl->key);
6496           pic16_outBitOp( result, pct2 );
6497         } else {
6498           pic16_emitpLabel(tlbl->key);
6499         }
6500
6501       } else {
6502         /* unsigned compare */      
6503         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6504
6505         compareAopfirstpass=1;
6506         while(size--) {
6507           
6508           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6509           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6510
6511         }
6512
6513         if(ifx)ifx->generated = 1;
6514         if(AOP_SIZE(result)) {
6515
6516           pic16_emitpLabel(falselbl->key);
6517           pic16_outBitC( result );
6518         }
6519
6520       }
6521     }
6522 }
6523
6524 #endif  /* } */
6525
6526
6527
6528 /*-----------------------------------------------------------------*/
6529 /* genCmpGt :- greater than comparison                             */
6530 /*-----------------------------------------------------------------*/
6531 static void genCmpGt (iCode *ic, iCode *ifx)
6532 {
6533   operand *left, *right, *result;
6534   sym_link *letype , *retype;
6535   int sign ;
6536
6537     FENTRY;
6538     
6539     left = IC_LEFT(ic);
6540     right= IC_RIGHT(ic);
6541     result = IC_RESULT(ic);
6542
6543     letype = getSpec(operandType(left));
6544     retype =getSpec(operandType(right));
6545     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6546     /* assign the amsops */
6547     pic16_aopOp (left,ic,FALSE);
6548     pic16_aopOp (right,ic,FALSE);
6549     pic16_aopOp (result,ic,TRUE);
6550
6551     genCmp(right, left, result, ifx, sign);
6552
6553     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6554     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6555     pic16_freeAsmop(result,NULL,ic,TRUE); 
6556 }
6557
6558 /*-----------------------------------------------------------------*/
6559 /* genCmpLt - less than comparisons                                */
6560 /*-----------------------------------------------------------------*/
6561 static void genCmpLt (iCode *ic, iCode *ifx)
6562 {
6563   operand *left, *right, *result;
6564   sym_link *letype , *retype;
6565   int sign ;
6566
6567     FENTRY;
6568
6569     left = IC_LEFT(ic);
6570     right= IC_RIGHT(ic);
6571     result = IC_RESULT(ic);
6572
6573     letype = getSpec(operandType(left));
6574     retype =getSpec(operandType(right));
6575     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6576
6577     /* assign the amsops */
6578     pic16_aopOp (left,ic,FALSE);
6579     pic16_aopOp (right,ic,FALSE);
6580     pic16_aopOp (result,ic,TRUE);
6581
6582     genCmp(left, right, result, ifx, sign);
6583
6584     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6585     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6586     pic16_freeAsmop(result,NULL,ic,TRUE); 
6587 }
6588
6589 #if 0
6590 // not needed ATM
6591 // FIXME reenable literal optimisation when the pic16 port is stable
6592
6593 /*-----------------------------------------------------------------*/
6594 /* genc16bit2lit - compare a 16 bit value to a literal             */
6595 /*-----------------------------------------------------------------*/
6596 static void genc16bit2lit(operand *op, int lit, int offset)
6597 {
6598   int i;
6599
6600   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6601   if( (lit&0xff) == 0) 
6602     i=1;
6603   else
6604     i=0;
6605
6606   switch( BYTEofLONG(lit,i)) { 
6607   case 0:
6608     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6609     break;
6610   case 1:
6611     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6612     break;
6613   case 0xff:
6614     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6615     break;
6616   default:
6617     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6618     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6619   }
6620
6621   i ^= 1;
6622
6623   switch( BYTEofLONG(lit,i)) { 
6624   case 0:
6625     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6626     break;
6627   case 1:
6628     emitSKPNZ;
6629     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6630     break;
6631   case 0xff:
6632     emitSKPNZ;
6633     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6634     break;
6635   default:
6636     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6637     emitSKPNZ;
6638     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6639
6640   }
6641
6642 }
6643 #endif
6644
6645 #if 0
6646 // not needed ATM
6647 /*-----------------------------------------------------------------*/
6648 /* gencjneshort - compare and jump if not equal                    */
6649 /*-----------------------------------------------------------------*/
6650 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6651 {
6652   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6653   int offset = 0;
6654   int res_offset = 0;  /* the result may be a different size then left or right */
6655   int res_size = AOP_SIZE(result);
6656   resolvedIfx rIfx;
6657   symbol *lbl, *lbl_done;
6658
6659   unsigned long lit = 0L;
6660   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6661
6662   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6663   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6664   if(result)
6665     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6666   resolveIfx(&rIfx,ifx);
6667   lbl =  newiTempLabel(NULL);
6668   lbl_done =  newiTempLabel(NULL);
6669
6670
6671   /* if the left side is a literal or 
6672      if the right is in a pointer register and left 
6673      is not */
6674   if ((AOP_TYPE(left) == AOP_LIT) || 
6675       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6676     operand *t = right;
6677     right = left;
6678     left = t;
6679   }
6680   if(AOP_TYPE(right) == AOP_LIT)
6681     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6682
6683   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6684     preserve_result = 1;
6685
6686   if(result && !preserve_result)
6687     {
6688       int i;
6689       for(i = 0; i < AOP_SIZE(result); i++)
6690         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6691     }
6692
6693
6694   /* if the right side is a literal then anything goes */
6695   if (AOP_TYPE(right) == AOP_LIT &&
6696       AOP_TYPE(left) != AOP_DIR ) {
6697     switch(size) {
6698     case 2:
6699       genc16bit2lit(left, lit, 0);
6700       emitSKPZ;
6701       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6702       break;
6703     default:
6704       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6705       while (size--) {
6706         if(lit & 0xff) {
6707           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6708           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6709         } else {
6710           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6711         }
6712
6713         emitSKPZ;
6714         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6715         offset++;
6716         if(res_offset < res_size-1)
6717           res_offset++;
6718         lit >>= 8;
6719       }
6720       break;
6721     }
6722   }
6723
6724   /* if the right side is in a register or in direct space or
6725      if the left is a pointer register & right is not */    
6726   else if (AOP_TYPE(right) == AOP_REG ||
6727            AOP_TYPE(right) == AOP_DIR || 
6728            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6729            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6730     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6731     int lbl_key = lbl->key;
6732
6733     if(result) {
6734       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6735       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6736     }else {
6737       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6738       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6739               __FUNCTION__,__LINE__);
6740       return;
6741     }
6742    
6743 /*     switch(size) { */
6744 /*     case 2: */
6745 /*       genc16bit2lit(left, lit, 0); */
6746 /*       emitSKPNZ; */
6747 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6748 /*       break; */
6749 /*     default: */
6750     while (size--) {
6751       int emit_skip=1;
6752       if((AOP_TYPE(left) == AOP_DIR) && 
6753          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6754
6755         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6756         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6757
6758       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6759             
6760         switch (lit & 0xff) {
6761         case 0:
6762           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6763           break;
6764         case 1:
6765           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6766           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6767           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6768           emit_skip=0;
6769           break;
6770         case 0xff:
6771           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6772           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6773           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6774           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6775           emit_skip=0;
6776           break;
6777         default:
6778           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6779           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6780         }
6781         lit >>= 8;
6782
6783       } else {
6784         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6785       }
6786       if(emit_skip) {
6787         if(AOP_TYPE(result) == AOP_CRY) {
6788           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6789           if(rIfx.condition)
6790             emitSKPNZ;
6791           else
6792             emitSKPZ;
6793           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6794         } else {
6795           /* fix me. probably need to check result size too */
6796           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6797           if(rIfx.condition)
6798             emitSKPZ;
6799           else
6800             emitSKPNZ;
6801           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6802           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6803         }
6804         if(ifx)
6805           ifx->generated=1;
6806       }
6807       emit_skip++;
6808       offset++;
6809       if(res_offset < res_size-1)
6810         res_offset++;
6811     }
6812 /*       break; */
6813 /*     } */
6814   } else if(AOP_TYPE(right) == AOP_REG &&
6815             AOP_TYPE(left) != AOP_DIR){
6816
6817     while(size--) {
6818       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6819       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6820       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6821       if(rIfx.condition)
6822         emitSKPNZ;
6823       else
6824         emitSKPZ;
6825       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6826       offset++;
6827       if(res_offset < res_size-1)
6828         res_offset++;
6829     }
6830       
6831   }else{
6832     /* right is a pointer reg need both a & b */
6833     while(size--) {
6834       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6835       if(strcmp(l,"b"))
6836         pic16_emitcode("mov","b,%s",l);
6837       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6838       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6839       offset++;
6840     }
6841   }
6842
6843   if(result && preserve_result)
6844     {
6845       int i;
6846       for(i = 0; i < AOP_SIZE(result); i++)
6847         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6848     }
6849
6850   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6851
6852   if(result && preserve_result)
6853     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6854
6855   if(!rIfx.condition)
6856     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6857
6858   pic16_emitpLabel(lbl->key);
6859
6860   if(result && preserve_result)
6861     {
6862       int i;
6863       for(i = 0; i < AOP_SIZE(result); i++)
6864         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6865
6866       pic16_emitpLabel(lbl_done->key);
6867    }
6868
6869   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6870
6871   if(ifx)
6872     ifx->generated = 1;
6873 }
6874 #endif
6875
6876 #if 0
6877 /*-----------------------------------------------------------------*/
6878 /* gencjne - compare and jump if not equal                         */
6879 /*-----------------------------------------------------------------*/
6880 static void gencjne(operand *left, operand *right, iCode *ifx)
6881 {
6882     symbol *tlbl  = newiTempLabel(NULL);
6883
6884     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6885     gencjneshort(left, right, lbl);
6886
6887     pic16_emitcode("mov","a,%s",one);
6888     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6889     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6890     pic16_emitcode("clr","a");
6891     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6892
6893     pic16_emitpLabel(lbl->key);
6894     pic16_emitpLabel(tlbl->key);
6895
6896 }
6897 #endif
6898
6899
6900 /*-----------------------------------------------------------------*/
6901 /* is_LitOp - check if operand has to be treated as literal        */
6902 /*-----------------------------------------------------------------*/
6903 static bool is_LitOp(operand *op)
6904 {
6905   return ((AOP_TYPE(op) == AOP_LIT)
6906       || ( (AOP_TYPE(op) == AOP_PCODE)
6907           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6908               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6909 }
6910
6911 /*-----------------------------------------------------------------*/
6912 /* is_LitAOp - check if operand has to be treated as literal        */
6913 /*-----------------------------------------------------------------*/
6914 static bool is_LitAOp(asmop *aop)
6915 {
6916   return ((aop->type == AOP_LIT)
6917       || ( (aop->type == AOP_PCODE)
6918           && ( (aop->aopu.pcop->type == PO_LITERAL)
6919               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6920 }
6921
6922
6923
6924 /*-----------------------------------------------------------------*/
6925 /* genCmpEq - generates code for equal to                          */
6926 /*-----------------------------------------------------------------*/
6927 static void genCmpEq (iCode *ic, iCode *ifx)
6928 {
6929   operand *left, *right, *result;
6930   symbol *falselbl = newiTempLabel(NULL);
6931   symbol *donelbl = newiTempLabel(NULL);
6932
6933   int preserve_result = 0;
6934   int generate_result = 0;
6935   int i=0;
6936   unsigned long lit = -1;
6937
6938   FENTRY;
6939   
6940   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6941   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6942   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6943  
6944   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6945
6946   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6947     {
6948       werror(W_POSSBUG2, __FILE__, __LINE__);
6949       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6950       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6951       goto release;
6952     }
6953
6954   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6955     {
6956       operand *tmp = right ;
6957       right = left;
6958       left = tmp;
6959     }
6960
6961   if (AOP_TYPE(right) == AOP_LIT) {
6962     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6963   }
6964
6965   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6966     preserve_result = 1;
6967
6968   if(result && AOP_SIZE(result))
6969     generate_result = 1;
6970
6971   if(generate_result && !preserve_result)
6972     {
6973       for(i = 0; i < AOP_SIZE(result); i++)
6974         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6975     }
6976
6977   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6978   for(i=0; i < AOP_SIZE(left); i++)
6979     {
6980       if(AOP_TYPE(left) != AOP_ACC)
6981         {
6982           if(is_LitOp(left))
6983             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6984           else
6985             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6986         }
6987       if(is_LitOp(right)) {
6988         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6989           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6990         }
6991       } else
6992         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6993
6994       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6995     }
6996
6997   // result == true
6998
6999   if(generate_result && preserve_result)
7000     {
7001       for(i = 0; i < AOP_SIZE(result); i++)
7002         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7003     }
7004
7005   if(generate_result)
7006     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7007
7008   if(generate_result && preserve_result)
7009     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7010
7011   if(ifx && IC_TRUE(ifx))
7012     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7013
7014   if(ifx && IC_FALSE(ifx))
7015     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7016
7017   pic16_emitpLabel(falselbl->key);
7018
7019   // result == false
7020
7021   if(ifx && IC_FALSE(ifx))
7022     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7023
7024   if(generate_result && preserve_result)
7025     {
7026       for(i = 0; i < AOP_SIZE(result); i++)
7027         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7028     }
7029
7030   pic16_emitpLabel(donelbl->key);
7031
7032   if(ifx)
7033     ifx->generated = 1;
7034
7035 release:
7036   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7037   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7038   pic16_freeAsmop(result,NULL,ic,TRUE);
7039
7040 }
7041
7042
7043 #if 0
7044 // old version kept for reference
7045
7046 /*-----------------------------------------------------------------*/
7047 /* genCmpEq - generates code for equal to                          */
7048 /*-----------------------------------------------------------------*/
7049 static void genCmpEq (iCode *ic, iCode *ifx)
7050 {
7051     operand *left, *right, *result;
7052     unsigned long lit = 0L;
7053     int size,offset=0;
7054     symbol *falselbl  = newiTempLabel(NULL);
7055
7056
7057     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7058
7059     if(ifx)
7060       DEBUGpic16_emitcode ("; ifx is non-null","");
7061     else
7062       DEBUGpic16_emitcode ("; ifx is null","");
7063
7064     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7065     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7066     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7067
7068     size = max(AOP_SIZE(left),AOP_SIZE(right));
7069
7070     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7071
7072     /* if literal, literal on the right or 
7073     if the right is in a pointer register and left 
7074     is not */
7075     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7076         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7077       operand *tmp = right ;
7078       right = left;
7079       left = tmp;
7080     }
7081
7082
7083     if(ifx && !AOP_SIZE(result)){
7084         symbol *tlbl;
7085         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7086         /* if they are both bit variables */
7087         if (AOP_TYPE(left) == AOP_CRY &&
7088             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7089                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7090             if(AOP_TYPE(right) == AOP_LIT){
7091                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7092                 if(lit == 0L){
7093                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7094                     pic16_emitcode("cpl","c");
7095                 } else if(lit == 1L) {
7096                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7097                 } else {
7098                     pic16_emitcode("clr","c");
7099                 }
7100                 /* AOP_TYPE(right) == AOP_CRY */
7101             } else {
7102                 symbol *lbl = newiTempLabel(NULL);
7103                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7104                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7105                 pic16_emitcode("cpl","c");
7106                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7107             }
7108             /* if true label then we jump if condition
7109             supplied is true */
7110             tlbl = newiTempLabel(NULL);
7111             if ( IC_TRUE(ifx) ) {
7112                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7113                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7114             } else {
7115                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7116                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7117             }
7118             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7119
7120                 {
7121                 /* left and right are both bit variables, result is carry */
7122                         resolvedIfx rIfx;
7123               
7124                         resolveIfx(&rIfx,ifx);
7125
7126                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7127                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7128                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7129                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7130                         genSkipz2(&rIfx,0);
7131                 }
7132         } else {
7133
7134                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7135
7136                         /* They're not both bit variables. Is the right a literal? */
7137                         if(AOP_TYPE(right) == AOP_LIT) {
7138                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7139             
7140                         switch(size) {
7141
7142                                 case 1:
7143                                         switch(lit & 0xff) {
7144                                                 case 1:
7145                                                                 if ( IC_TRUE(ifx) ) {
7146                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7147                                                                         emitSKPNZ;
7148                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7149                                                                 } else {
7150                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7151                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7152                                                                 }
7153                                                                 break;
7154                                                 case 0xff:
7155                                                                 if ( IC_TRUE(ifx) ) {
7156                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7157                                                                         emitSKPNZ;
7158                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7159                                                                 } else {
7160                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7161                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7162                                                                 }
7163                                                                 break;
7164                                                 default:
7165                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7166                                                                 if(lit)
7167                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7168                                                                 genSkip(ifx,'z');
7169                                         } // switch lit
7170
7171
7172                                         /* end of size == 1 */
7173                                         break;
7174               
7175                                 case 2:
7176                                         genc16bit2lit(left,lit,offset);
7177                                         genSkip(ifx,'z');
7178                                         break;
7179                                         /* end of size == 2 */
7180
7181                                 default:
7182                                         /* size is 4 */
7183                                         if(lit==0) {
7184                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7185                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7186                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7187                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7188                                                 genSkip(ifx,'z');
7189                                         } else {
7190                                                 /* search for patterns that can be optimized */
7191
7192                                                 genc16bit2lit(left,lit,0);
7193                                                 lit >>= 16;
7194                                                 if(lit) {
7195                                                                 if(IC_TRUE(ifx))
7196                                                                 emitSKPZ; // if hi word unequal
7197                                                                 else
7198                                                                 emitSKPNZ; // if hi word equal
7199                                                                 // fail early
7200                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7201                                                         genc16bit2lit(left,lit,2);
7202                                                         genSkip(ifx,'z');
7203                                                 } else {
7204                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7205                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7206                                                         genSkip(ifx,'z');
7207                                                 }
7208                                         }
7209                                                 pic16_emitpLabel(falselbl->key);
7210                                                 break;
7211
7212                         } // switch size
7213           
7214                         ifx->generated = 1;
7215                         goto release ;
7216             
7217
7218           } else if(AOP_TYPE(right) == AOP_CRY ) {
7219             /* we know the left is not a bit, but that the right is */
7220             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7221             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7222                       pic16_popGet(AOP(right),offset));
7223             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7224
7225             /* if the two are equal, then W will be 0 and the Z bit is set
7226              * we could test Z now, or go ahead and check the high order bytes if
7227              * the variable we're comparing is larger than a byte. */
7228
7229             while(--size)
7230               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7231
7232             if ( IC_TRUE(ifx) ) {
7233               emitSKPNZ;
7234               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7235               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7236             } else {
7237               emitSKPZ;
7238               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7239               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7240             }
7241
7242           } else {
7243             /* They're both variables that are larger than bits */
7244             int s = size;
7245
7246             tlbl = newiTempLabel(NULL);
7247
7248             while(size--) {
7249               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7250               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7251
7252               if ( IC_TRUE(ifx) ) {
7253                 if(size) {
7254                   emitSKPZ;
7255                 
7256                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7257
7258                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7259                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7260                 } else {
7261                   emitSKPNZ;
7262
7263                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7264
7265
7266                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7267                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7268                 }
7269               } else {
7270                 emitSKPZ;
7271
7272                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7273
7274                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7275                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7276               }
7277               offset++;
7278             }
7279             if(s>1 && IC_TRUE(ifx)) {
7280               pic16_emitpLabel(tlbl->key);
7281               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7282             }
7283           }
7284         }
7285         /* mark the icode as generated */
7286         ifx->generated = 1;
7287         goto release ;
7288     }
7289
7290     /* if they are both bit variables */
7291     if (AOP_TYPE(left) == AOP_CRY &&
7292         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7293         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7294         if(AOP_TYPE(right) == AOP_LIT){
7295             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7296             if(lit == 0L){
7297                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7298                 pic16_emitcode("cpl","c");
7299             } else if(lit == 1L) {
7300                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7301             } else {
7302                 pic16_emitcode("clr","c");
7303             }
7304             /* AOP_TYPE(right) == AOP_CRY */
7305         } else {
7306             symbol *lbl = newiTempLabel(NULL);
7307             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7308             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7309             pic16_emitcode("cpl","c");
7310             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7311         }
7312         /* c = 1 if egal */
7313         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7314             pic16_outBitC(result);
7315             goto release ;
7316         }
7317         if (ifx) {
7318             genIfxJump (ifx,"c");
7319             goto release ;
7320         }
7321         /* if the result is used in an arithmetic operation
7322         then put the result in place */
7323         pic16_outBitC(result);
7324     } else {
7325       
7326       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7327       gencjne(left,right,result,ifx);
7328 /*
7329       if(ifx) 
7330         gencjne(left,right,newiTempLabel(NULL));
7331       else {
7332         if(IC_TRUE(ifx)->key)
7333           gencjne(left,right,IC_TRUE(ifx)->key);
7334         else
7335           gencjne(left,right,IC_FALSE(ifx)->key);
7336         ifx->generated = 1;
7337         goto release ;
7338       }
7339       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7340         pic16_aopPut(AOP(result),"a",0);
7341         goto release ;
7342       }
7343
7344       if (ifx) {
7345         genIfxJump (ifx,"a");
7346         goto release ;
7347       }
7348 */
7349       /* if the result is used in an arithmetic operation
7350          then put the result in place */
7351 /*
7352       if (AOP_TYPE(result) != AOP_CRY) 
7353         pic16_outAcc(result);
7354 */
7355       /* leave the result in acc */
7356     }
7357
7358 release:
7359     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7360     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7361     pic16_freeAsmop(result,NULL,ic,TRUE);
7362 }
7363 #endif
7364
7365 /*-----------------------------------------------------------------*/
7366 /* ifxForOp - returns the icode containing the ifx for operand     */
7367 /*-----------------------------------------------------------------*/
7368 static iCode *ifxForOp ( operand *op, iCode *ic )
7369 {
7370   FENTRY2;
7371
7372     /* if true symbol then needs to be assigned */
7373     if (IS_TRUE_SYMOP(op))
7374         return NULL ;
7375
7376     /* if this has register type condition and
7377     the next instruction is ifx with the same operand
7378     and live to of the operand is upto the ifx only then */
7379     if (ic->next
7380         && ic->next->op == IFX
7381         && IC_COND(ic->next)->key == op->key
7382         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7383         ) {
7384                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7385           return ic->next;
7386     }
7387
7388     /*
7389     if (ic->next &&
7390         ic->next->op == IFX &&
7391         IC_COND(ic->next)->key == op->key) {
7392       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7393       return ic->next;
7394     }
7395     */
7396
7397     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7398     if (ic->next &&
7399         ic->next->op == IFX)
7400       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7401
7402     if (ic->next &&
7403         ic->next->op == IFX &&
7404         IC_COND(ic->next)->key == op->key) {
7405       DEBUGpic16_emitcode ("; "," key is okay");
7406       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7407                            OP_SYMBOL(op)->liveTo,
7408                            ic->next->seq);
7409     }
7410
7411 #if 0
7412     /* the code below is completely untested
7413      * it just allows ulong2fs.c compile -- VR */
7414          
7415     ic = ic->next;
7416     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7417                                         __FILE__, __FUNCTION__, __LINE__);
7418         
7419     /* if this has register type condition and
7420     the next instruction is ifx with the same operand
7421     and live to of the operand is upto the ifx only then */
7422     if (ic->next &&
7423         ic->next->op == IFX &&
7424         IC_COND(ic->next)->key == op->key &&
7425         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7426         return ic->next;
7427
7428     if (ic->next &&
7429         ic->next->op == IFX &&
7430         IC_COND(ic->next)->key == op->key) {
7431       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7432       return ic->next;
7433     }
7434
7435     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7436                                         __FILE__, __FUNCTION__, __LINE__);
7437
7438 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7439 #endif
7440
7441     return NULL;
7442 }
7443 /*-----------------------------------------------------------------*/
7444 /* genAndOp - for && operation                                     */
7445 /*-----------------------------------------------------------------*/
7446 static void genAndOp (iCode *ic)
7447 {
7448   operand *left,*right, *result;
7449 /*     symbol *tlbl; */
7450
7451     FENTRY;
7452
7453     /* note here that && operations that are in an
7454     if statement are taken away by backPatchLabels
7455     only those used in arthmetic operations remain */
7456     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7457     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7458     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7459
7460     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7461
7462     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7463     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7464     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7465
7466     /* if both are bit variables */
7467 /*     if (AOP_TYPE(left) == AOP_CRY && */
7468 /*         AOP_TYPE(right) == AOP_CRY ) { */
7469 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7470 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7471 /*         pic16_outBitC(result); */
7472 /*     } else { */
7473 /*         tlbl = newiTempLabel(NULL); */
7474 /*         pic16_toBoolean(left);     */
7475 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7476 /*         pic16_toBoolean(right); */
7477 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7478 /*         pic16_outBitAcc(result); */
7479 /*     } */
7480
7481     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7482     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7483     pic16_freeAsmop(result,NULL,ic,TRUE);
7484 }
7485
7486
7487 /*-----------------------------------------------------------------*/
7488 /* genOrOp - for || operation                                      */
7489 /*-----------------------------------------------------------------*/
7490 /*
7491   tsd pic port -
7492   modified this code, but it doesn't appear to ever get called
7493 */
7494
7495 static void genOrOp (iCode *ic)
7496 {
7497   operand *left,*right, *result;
7498   symbol *tlbl;
7499
7500     FENTRY;  
7501
7502   /* note here that || operations that are in an
7503     if statement are taken away by backPatchLabels
7504     only those used in arthmetic operations remain */
7505     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7506     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7507     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7508
7509     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7510
7511     /* if both are bit variables */
7512     if (AOP_TYPE(left) == AOP_CRY &&
7513         AOP_TYPE(right) == AOP_CRY ) {
7514       pic16_emitcode("clrc","");
7515       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7516                AOP(left)->aopu.aop_dir,
7517                AOP(left)->aopu.aop_dir);
7518       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7519                AOP(right)->aopu.aop_dir,
7520                AOP(right)->aopu.aop_dir);
7521       pic16_emitcode("setc","");
7522
7523     } else {
7524         tlbl = newiTempLabel(NULL);
7525         pic16_toBoolean(left);
7526         emitSKPZ;
7527         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7528         pic16_toBoolean(right);
7529         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7530
7531         pic16_outBitAcc(result);
7532     }
7533
7534     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7535     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7536     pic16_freeAsmop(result,NULL,ic,TRUE);            
7537 }
7538
7539 /*-----------------------------------------------------------------*/
7540 /* isLiteralBit - test if lit == 2^n                               */
7541 /*-----------------------------------------------------------------*/
7542 static int isLiteralBit(unsigned long lit)
7543 {
7544     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7545     0x100L,0x200L,0x400L,0x800L,
7546     0x1000L,0x2000L,0x4000L,0x8000L,
7547     0x10000L,0x20000L,0x40000L,0x80000L,
7548     0x100000L,0x200000L,0x400000L,0x800000L,
7549     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7550     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7551     int idx;
7552     
7553     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7554     for(idx = 0; idx < 32; idx++)
7555         if(lit == pw[idx])
7556             return idx+1;
7557     return 0;
7558 }
7559
7560 /*-----------------------------------------------------------------*/
7561 /* continueIfTrue -                                                */
7562 /*-----------------------------------------------------------------*/
7563 static void continueIfTrue (iCode *ic)
7564 {
7565   FENTRY;
7566   if(IC_TRUE(ic))
7567     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7568   ic->generated = 1;
7569 }
7570
7571 /*-----------------------------------------------------------------*/
7572 /* jmpIfTrue -                                                     */
7573 /*-----------------------------------------------------------------*/
7574 static void jumpIfTrue (iCode *ic)
7575 {
7576   FENTRY;
7577   if(!IC_TRUE(ic))
7578     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7579   ic->generated = 1;
7580 }
7581
7582 /*-----------------------------------------------------------------*/
7583 /* jmpTrueOrFalse -                                                */
7584 /*-----------------------------------------------------------------*/
7585 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7586 {
7587   // ugly but optimized by peephole
7588   FENTRY;
7589   if(IC_TRUE(ic)){
7590     symbol *nlbl = newiTempLabel(NULL);
7591       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7592       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7593       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7594       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7595   } else {
7596     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7597     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7598   }
7599   ic->generated = 1;
7600 }
7601
7602 /*-----------------------------------------------------------------*/
7603 /* genAnd  - code for and                                          */
7604 /*-----------------------------------------------------------------*/
7605 static void genAnd (iCode *ic, iCode *ifx)
7606 {
7607   operand *left, *right, *result;
7608   int size, offset=0;  
7609   unsigned long lit = 0L;
7610   int bytelit = 0;
7611   resolvedIfx rIfx;
7612
7613     FENTRY;
7614     
7615   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7616   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7617   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7618
7619   resolveIfx(&rIfx,ifx);
7620
7621   /* if left is a literal & right is not then exchange them */
7622   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7623       AOP_NEEDSACC(left)) {
7624     operand *tmp = right ;
7625     right = left;
7626     left = tmp;
7627   }
7628
7629   /* if result = right then exchange them */
7630   if(pic16_sameRegs(AOP(result),AOP(right))){
7631     operand *tmp = right ;
7632     right = left;
7633     left = tmp;
7634   }
7635
7636   /* if right is bit then exchange them */
7637   if (AOP_TYPE(right) == AOP_CRY &&
7638       AOP_TYPE(left) != AOP_CRY){
7639     operand *tmp = right ;
7640     right = left;
7641     left = tmp;
7642   }
7643   if(AOP_TYPE(right) == AOP_LIT)
7644     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7645
7646   size = AOP_SIZE(result);
7647
7648   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7649
7650   // if(bit & yy)
7651   // result = bit & yy;
7652   if (AOP_TYPE(left) == AOP_CRY){
7653     // c = bit & literal;
7654     if(AOP_TYPE(right) == AOP_LIT){
7655       if(lit & 1) {
7656         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7657           // no change
7658           goto release;
7659         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7660       } else {
7661         // bit(result) = 0;
7662         if(size && (AOP_TYPE(result) == AOP_CRY)){
7663           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7664           goto release;
7665         }
7666         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7667           jumpIfTrue(ifx);
7668           goto release;
7669         }
7670         pic16_emitcode("clr","c");
7671       }
7672     } else {
7673       if (AOP_TYPE(right) == AOP_CRY){
7674         // c = bit & bit;
7675         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7676         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7677       } else {
7678         // c = bit & val;
7679         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7680         // c = lsb
7681         pic16_emitcode("rrc","a");
7682         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7683       }
7684     }
7685     // bit = c
7686     // val = c
7687     if(size)
7688       pic16_outBitC(result);
7689     // if(bit & ...)
7690     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7691       genIfxJump(ifx, "c");           
7692     goto release ;
7693   }
7694
7695   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7696   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7697   if((AOP_TYPE(right) == AOP_LIT) &&
7698      (AOP_TYPE(result) == AOP_CRY) &&
7699      (AOP_TYPE(left) != AOP_CRY)){
7700     int posbit = isLiteralBit(lit);
7701     /* left &  2^n */
7702     if(posbit){
7703       posbit--;
7704       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7705       // bit = left & 2^n
7706       if(size)
7707         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7708       // if(left &  2^n)
7709       else{
7710         if(ifx){
7711 /*
7712           if(IC_TRUE(ifx)) {
7713             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7714             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7715           } else {
7716             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7717             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7718           }
7719 */
7720         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7721         size = AOP_SIZE(left);
7722
7723         {
7724           int bp = posbit, ofs=0;
7725           
7726             while(bp > 7) {
7727               bp -= 8;
7728               ofs++;
7729             }
7730
7731           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7732                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7733
7734         }
7735 /*
7736           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7737                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7738 */
7739           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7740           
7741           ifx->generated = 1;
7742         }
7743         goto release;
7744       }
7745     } else {
7746       symbol *tlbl = newiTempLabel(NULL);
7747       int sizel = AOP_SIZE(left);
7748
7749       if(size)
7750         emitSETC;
7751
7752       while(sizel--) {
7753         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7754
7755           /* patch provided by Aaron Colwell */
7756           if((posbit = isLiteralBit(bytelit)) != 0) {
7757               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7758                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7759                                                 (posbit-1),0, PO_GPR_REGISTER));
7760
7761               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7762 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7763           } else {
7764               if (bytelit == 0xff) {
7765                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7766                    * a peephole could optimize it out -- VR */
7767                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7768               } else {
7769                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7770                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7771               }
7772
7773               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7774                             pic16_popGetLabel(tlbl->key));
7775           }
7776         
7777 #if 0
7778           /* old code, left here for reference -- VR 09/2004 */
7779           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7780           // byte ==  2^n ?
7781           if((posbit = isLiteralBit(bytelit)) != 0)
7782             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7783           else{
7784             if(bytelit != 0x0FFL)
7785               pic16_emitcode("anl","a,%s",
7786                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7787             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7788           }
7789 #endif
7790         }
7791         offset++;
7792       }
7793       // bit = left & literal
7794       if(size) {
7795         emitCLRC;
7796         pic16_emitpLabel(tlbl->key);
7797       }
7798       // if(left & literal)
7799       else {
7800         if(ifx) {
7801           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7802           ifx->generated = 1;
7803         }
7804         pic16_emitpLabel(tlbl->key);
7805         goto release;
7806       }
7807     }
7808
7809     pic16_outBitC(result);
7810     goto release ;
7811   }
7812
7813   /* if left is same as result */
7814   if(pic16_sameRegs(AOP(result),AOP(left))){
7815     int know_W = -1;
7816     for(;size--; offset++,lit>>=8) {
7817       if(AOP_TYPE(right) == AOP_LIT){
7818         switch(lit & 0xff) {
7819         case 0x00:
7820           /*  and'ing with 0 has clears the result */
7821 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7822           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7823           break;
7824         case 0xff:
7825           /* and'ing with 0xff is a nop when the result and left are the same */
7826           break;
7827
7828         default:
7829           {
7830             int p = pic16_my_powof2( (~lit) & 0xff );
7831             if(p>=0) {
7832               /* only one bit is set in the literal, so use a bcf instruction */
7833 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7834               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7835
7836             } else {
7837               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7838               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7839               if(know_W != (lit&0xff))
7840                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7841               know_W = lit &0xff;
7842               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7843             }
7844           }    
7845         }
7846       } else {
7847         if (AOP_TYPE(left) == AOP_ACC) {
7848           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7849         } else {                    
7850           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7851           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7852
7853         }
7854       }
7855     }
7856
7857   } else {
7858     // left & result in different registers
7859     if(AOP_TYPE(result) == AOP_CRY){
7860       // result = bit
7861       // if(size), result in bit
7862       // if(!size && ifx), conditional oper: if(left & right)
7863       symbol *tlbl = newiTempLabel(NULL);
7864       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7865       if(size)
7866         pic16_emitcode("setb","c");
7867       while(sizer--){
7868         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7869         pic16_emitcode("anl","a,%s",
7870                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7871         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7872         offset++;
7873       }
7874       if(size){
7875         CLRC;
7876         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7877         pic16_outBitC(result);
7878       } else if(ifx)
7879         jmpTrueOrFalse(ifx, tlbl);
7880     } else {
7881       for(;(size--);offset++) {
7882         // normal case
7883         // result = left & right
7884         if(AOP_TYPE(right) == AOP_LIT){
7885           int t = (lit >> (offset*8)) & 0x0FFL;
7886           switch(t) { 
7887           case 0x00:
7888             pic16_emitcode("clrf","%s",
7889                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7890             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7891             break;
7892           case 0xff:
7893             pic16_emitcode("movf","%s,w",
7894                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7895             pic16_emitcode("movwf","%s",
7896                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7897             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7898             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7899             break;
7900           default:
7901             pic16_emitcode("movlw","0x%x",t);
7902             pic16_emitcode("andwf","%s,w",
7903                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7904             pic16_emitcode("movwf","%s",
7905                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7906               
7907             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7908             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7909             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7910           }
7911           continue;
7912         }
7913
7914         if (AOP_TYPE(left) == AOP_ACC) {
7915           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7916           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7917         } else {
7918           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7919           pic16_emitcode("andwf","%s,w",
7920                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7921           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7922           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7923         }
7924         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7925         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7926       }
7927     }
7928   }
7929
7930   release :
7931     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7932   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7933   pic16_freeAsmop(result,NULL,ic,TRUE);     
7934 }
7935
7936 /*-----------------------------------------------------------------*/
7937 /* genOr  - code for or                                            */
7938 /*-----------------------------------------------------------------*/
7939 static void genOr (iCode *ic, iCode *ifx)
7940 {
7941     operand *left, *right, *result;
7942     int size, offset=0;
7943     unsigned long lit = 0L;
7944
7945     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7946     FENTRY;
7947
7948     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7949     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7950     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7951
7952     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7953
7954     /* if left is a literal & right is not then exchange them */
7955     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7956         AOP_NEEDSACC(left)) {
7957         operand *tmp = right ;
7958         right = left;
7959         left = tmp;
7960     }
7961
7962     /* if result = right then exchange them */
7963     if(pic16_sameRegs(AOP(result),AOP(right))){
7964         operand *tmp = right ;
7965         right = left;
7966         left = tmp;
7967     }
7968
7969     /* if right is bit then exchange them */
7970     if (AOP_TYPE(right) == AOP_CRY &&
7971         AOP_TYPE(left) != AOP_CRY){
7972         operand *tmp = right ;
7973         right = left;
7974         left = tmp;
7975     }
7976
7977     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7978
7979     if(AOP_TYPE(right) == AOP_LIT)
7980         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7981
7982     size = AOP_SIZE(result);
7983
7984     // if(bit | yy)
7985     // xx = bit | yy;
7986     if (AOP_TYPE(left) == AOP_CRY){
7987         if(AOP_TYPE(right) == AOP_LIT){
7988             // c = bit & literal;
7989             if(lit){
7990                 // lit != 0 => result = 1
7991                 if(AOP_TYPE(result) == AOP_CRY){
7992                   if(size)
7993                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7994                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7995                   //     AOP(result)->aopu.aop_dir,
7996                   //     AOP(result)->aopu.aop_dir);
7997                     else if(ifx)
7998                         continueIfTrue(ifx);
7999                     goto release;
8000                 }
8001             } else {
8002                 // lit == 0 => result = left
8003                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
8004                     goto release;
8005                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8006             }
8007         } else {
8008             if (AOP_TYPE(right) == AOP_CRY){
8009               if(pic16_sameRegs(AOP(result),AOP(left))){
8010                 // c = bit | bit;
8011                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8012                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8013                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8014
8015                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8016                          AOP(result)->aopu.aop_dir,
8017                          AOP(result)->aopu.aop_dir);
8018                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8019                          AOP(right)->aopu.aop_dir,
8020                          AOP(right)->aopu.aop_dir);
8021                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8022                          AOP(result)->aopu.aop_dir,
8023                          AOP(result)->aopu.aop_dir);
8024               } else {
8025                 if( AOP_TYPE(result) == AOP_ACC) {
8026                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8027                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8028                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8029                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8030
8031                 } else {
8032
8033                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8034                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8035                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8036                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8037
8038                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8039                                  AOP(result)->aopu.aop_dir,
8040                                  AOP(result)->aopu.aop_dir);
8041                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8042                                  AOP(right)->aopu.aop_dir,
8043                                  AOP(right)->aopu.aop_dir);
8044                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8045                                  AOP(left)->aopu.aop_dir,
8046                                  AOP(left)->aopu.aop_dir);
8047                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8048                                  AOP(result)->aopu.aop_dir,
8049                                  AOP(result)->aopu.aop_dir);
8050                 }
8051               }
8052             } else {
8053                 // c = bit | val;
8054                 symbol *tlbl = newiTempLabel(NULL);
8055                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8056
8057
8058                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8059                 if( AOP_TYPE(right) == AOP_ACC) {
8060                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8061                   emitSKPNZ;
8062                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8063                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8064                 }
8065
8066
8067
8068                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8069                     pic16_emitcode(";XXX setb","c");
8070                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8071                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8072                 pic16_toBoolean(right);
8073                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8074                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8075                     jmpTrueOrFalse(ifx, tlbl);
8076                     goto release;
8077                 } else {
8078                     CLRC;
8079                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8080                 }
8081             }
8082         }
8083         // bit = c
8084         // val = c
8085         if(size)
8086             pic16_outBitC(result);
8087         // if(bit | ...)
8088         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8089             genIfxJump(ifx, "c");           
8090         goto release ;
8091     }
8092
8093     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8094     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8095     if((AOP_TYPE(right) == AOP_LIT) &&
8096        (AOP_TYPE(result) == AOP_CRY) &&
8097        (AOP_TYPE(left) != AOP_CRY)){
8098         if(lit){
8099           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8100             // result = 1
8101             if(size)
8102                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8103             else 
8104                 continueIfTrue(ifx);
8105             goto release;
8106         } else {
8107           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8108             // lit = 0, result = boolean(left)
8109             if(size)
8110                 pic16_emitcode(";XXX setb","c");
8111             pic16_toBoolean(right);
8112             if(size){
8113                 symbol *tlbl = newiTempLabel(NULL);
8114                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8115                 CLRC;
8116                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8117             } else {
8118                 genIfxJump (ifx,"a");
8119                 goto release;
8120             }
8121         }
8122         pic16_outBitC(result);
8123         goto release ;
8124     }
8125
8126     /* if left is same as result */
8127     if(pic16_sameRegs(AOP(result),AOP(left))){
8128       int know_W = -1;
8129       for(;size--; offset++,lit>>=8) {
8130         if(AOP_TYPE(right) == AOP_LIT){
8131           if((lit & 0xff) == 0)
8132             /*  or'ing with 0 has no effect */
8133             continue;
8134           else {
8135             int p = pic16_my_powof2(lit & 0xff);
8136             if(p>=0) {
8137               /* only one bit is set in the literal, so use a bsf instruction */
8138               pic16_emitpcode(POC_BSF,
8139                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8140             } else {
8141               if(know_W != (lit & 0xff))
8142                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8143               know_W = lit & 0xff;
8144               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8145             }
8146                     
8147           }
8148         } else {
8149           if (AOP_TYPE(left) == AOP_ACC) {
8150             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8151 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8152           } else {                  
8153             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8154             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8155
8156 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8157 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8158
8159           }
8160         }
8161       }
8162     } else {
8163         // left & result in different registers
8164         if(AOP_TYPE(result) == AOP_CRY){
8165             // result = bit
8166             // if(size), result in bit
8167             // if(!size && ifx), conditional oper: if(left | right)
8168             symbol *tlbl = newiTempLabel(NULL);
8169             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8170             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8171
8172
8173             if(size)
8174                 pic16_emitcode(";XXX setb","c");
8175             while(sizer--){
8176                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8177                 pic16_emitcode(";XXX orl","a,%s",
8178                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8179                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8180                 offset++;
8181             }
8182             if(size){
8183                 CLRC;
8184                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8185                 pic16_outBitC(result);
8186             } else if(ifx)
8187                 jmpTrueOrFalse(ifx, tlbl);
8188         } else for(;(size--);offset++){
8189           // normal case
8190           // result = left & right
8191           if(AOP_TYPE(right) == AOP_LIT){
8192             int t = (lit >> (offset*8)) & 0x0FFL;
8193             switch(t) { 
8194             case 0x00:
8195               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8196               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8197
8198 //            pic16_emitcode("movf","%s,w",
8199 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8200 //            pic16_emitcode("movwf","%s",
8201 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8202               break;
8203             default:
8204               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8205               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8206               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8207
8208 //            pic16_emitcode("movlw","0x%x",t);
8209 //            pic16_emitcode("iorwf","%s,w",
8210 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8211 //            pic16_emitcode("movwf","%s",
8212 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8213               
8214             }
8215             continue;
8216           }
8217
8218           // faster than result <- left, anl result,right
8219           // and better if result is SFR
8220           if (AOP_TYPE(left) == AOP_ACC) {
8221             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8222 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8223           } else {
8224             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8225             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8226
8227 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8228 //          pic16_emitcode("iorwf","%s,w",
8229 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8230           }
8231           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8232 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8233         }
8234     }
8235
8236 release :
8237     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8238     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8239     pic16_freeAsmop(result,NULL,ic,TRUE);     
8240 }
8241
8242 /*-----------------------------------------------------------------*/
8243 /* genXor - code for xclusive or                                   */
8244 /*-----------------------------------------------------------------*/
8245 static void genXor (iCode *ic, iCode *ifx)
8246 {
8247   operand *left, *right, *result;
8248   int size, offset=0;
8249   unsigned long lit = 0L;
8250
8251   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8252   FENTRY;
8253
8254   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8255   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8256   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8257
8258   /* if left is a literal & right is not ||
8259      if left needs acc & right does not */
8260   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8261       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8262     operand *tmp = right ;
8263     right = left;
8264     left = tmp;
8265   }
8266
8267   /* if result = right then exchange them */
8268   if(pic16_sameRegs(AOP(result),AOP(right))){
8269     operand *tmp = right ;
8270     right = left;
8271     left = tmp;
8272   }
8273
8274   /* if right is bit then exchange them */
8275   if (AOP_TYPE(right) == AOP_CRY &&
8276       AOP_TYPE(left) != AOP_CRY){
8277     operand *tmp = right ;
8278     right = left;
8279     left = tmp;
8280   }
8281   if(AOP_TYPE(right) == AOP_LIT)
8282     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8283
8284   size = AOP_SIZE(result);
8285
8286   // if(bit ^ yy)
8287   // xx = bit ^ yy;
8288   if (AOP_TYPE(left) == AOP_CRY){
8289     if(AOP_TYPE(right) == AOP_LIT){
8290       // c = bit & literal;
8291       if(lit>>1){
8292         // lit>>1  != 0 => result = 1
8293         if(AOP_TYPE(result) == AOP_CRY){
8294           if(size)
8295             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8296             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8297           else if(ifx)
8298             continueIfTrue(ifx);
8299           goto release;
8300         }
8301         pic16_emitcode("setb","c");
8302       } else{
8303         // lit == (0 or 1)
8304         if(lit == 0){
8305           // lit == 0, result = left
8306           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8307             goto release;
8308           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8309         } else{
8310           // lit == 1, result = not(left)
8311           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8312             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8313             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8314             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8315             goto release;
8316           } else {
8317             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8318             pic16_emitcode("cpl","c");
8319           }
8320         }
8321       }
8322
8323     } else {
8324       // right != literal
8325       symbol *tlbl = newiTempLabel(NULL);
8326       if (AOP_TYPE(right) == AOP_CRY){
8327         // c = bit ^ bit;
8328         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8329       }
8330       else{
8331         int sizer = AOP_SIZE(right);
8332         // c = bit ^ val
8333         // if val>>1 != 0, result = 1
8334         pic16_emitcode("setb","c");
8335         while(sizer){
8336           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8337           if(sizer == 1)
8338             // test the msb of the lsb
8339             pic16_emitcode("anl","a,#0xfe");
8340           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8341           sizer--;
8342         }
8343         // val = (0,1)
8344         pic16_emitcode("rrc","a");
8345       }
8346       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8347       pic16_emitcode("cpl","c");
8348       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8349     }
8350     // bit = c
8351     // val = c
8352     if(size)
8353       pic16_outBitC(result);
8354     // if(bit | ...)
8355     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8356       genIfxJump(ifx, "c");           
8357     goto release ;
8358   }
8359
8360   if(pic16_sameRegs(AOP(result),AOP(left))){
8361     /* if left is same as result */
8362     for(;size--; offset++) {
8363       if(AOP_TYPE(right) == AOP_LIT){
8364         int t  = (lit >> (offset*8)) & 0x0FFL;
8365         if(t == 0x00L)
8366           continue;
8367         else
8368           if (IS_AOP_PREG(left)) {
8369             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8370             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8371             pic16_aopPut(AOP(result),"a",offset);
8372           } else {
8373             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8374             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8375             pic16_emitcode("xrl","%s,%s",
8376                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8377                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8378           }
8379       } else {
8380         if (AOP_TYPE(left) == AOP_ACC)
8381           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8382         else {
8383           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8384           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8385 /*
8386           if (IS_AOP_PREG(left)) {
8387             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8388             pic16_aopPut(AOP(result),"a",offset);
8389           } else
8390             pic16_emitcode("xrl","%s,a",
8391                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8392 */
8393         }
8394       }
8395     }
8396   } else {
8397     // left & result in different registers
8398     if(AOP_TYPE(result) == AOP_CRY){
8399       // result = bit
8400       // if(size), result in bit
8401       // if(!size && ifx), conditional oper: if(left ^ right)
8402       symbol *tlbl = newiTempLabel(NULL);
8403       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8404       if(size)
8405         pic16_emitcode("setb","c");
8406       while(sizer--){
8407         if((AOP_TYPE(right) == AOP_LIT) &&
8408            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8409           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8410         } else {
8411           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8412           pic16_emitcode("xrl","a,%s",
8413                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8414         }
8415         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8416         offset++;
8417       }
8418       if(size){
8419         CLRC;
8420         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8421         pic16_outBitC(result);
8422       } else if(ifx)
8423         jmpTrueOrFalse(ifx, tlbl);
8424     } else for(;(size--);offset++){
8425       // normal case
8426       // result = left & right
8427       if(AOP_TYPE(right) == AOP_LIT){
8428         int t = (lit >> (offset*8)) & 0x0FFL;
8429         switch(t) { 
8430         case 0x00:
8431           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8432           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8433           pic16_emitcode("movf","%s,w",
8434                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8435           pic16_emitcode("movwf","%s",
8436                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8437           break;
8438         case 0xff:
8439           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8440           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8441           pic16_emitcode("comf","%s,w",
8442                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8443           pic16_emitcode("movwf","%s",
8444                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8445           break;
8446         default:
8447           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8448           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8449           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8450           pic16_emitcode("movlw","0x%x",t);
8451           pic16_emitcode("xorwf","%s,w",
8452                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8453           pic16_emitcode("movwf","%s",
8454                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8455
8456         }
8457         continue;
8458       }
8459
8460       // faster than result <- left, anl result,right
8461       // and better if result is SFR
8462       if (AOP_TYPE(left) == AOP_ACC) {
8463         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8464         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8465       } else {
8466         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8467         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8468         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8469         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8470       }
8471       if ( AOP_TYPE(result) != AOP_ACC){
8472         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8473         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8474       }
8475     }
8476   }
8477
8478   release :
8479     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8480   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8481   pic16_freeAsmop(result,NULL,ic,TRUE);     
8482 }
8483
8484 /*-----------------------------------------------------------------*/
8485 /* genInline - write the inline code out                           */
8486 /*-----------------------------------------------------------------*/
8487 static void genInline (iCode *ic)
8488 {
8489   char *buffer, *bp, *bp1;
8490     
8491         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8492
8493         _G.inLine += (!options.asmpeep);
8494
8495         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8496         strcpy(buffer,IC_INLINE(ic));
8497         
8498         while((bp1=strstr(bp, "\\n"))) {
8499           *bp1++ = '\n';
8500           *bp1++ = ' ';
8501           bp = bp1;
8502         }
8503         bp = bp1 = buffer;
8504
8505 #if 0
8506   /* This is an experimental code for #pragma inline
8507      and is temporarily disabled for 2.5.0 release */
8508         if(asmInlineMap)
8509         {
8510           symbol *sym;
8511           char *s;
8512           char *cbuf;
8513           int cblen;
8514
8515             cbuf = Safe_strdup(buffer);
8516             cblen = strlen(buffer)+1;
8517             memset(cbuf, 0, cblen);
8518
8519             bp = buffer;
8520             bp1 = cbuf;
8521             while(*bp) {
8522               if(*bp != '%')*bp1++ = *bp++;
8523               else {
8524                 int i;
8525
8526                   bp++;
8527                   i = *bp - '0';
8528                   if(i>elementsInSet(asmInlineMap))break;
8529                   
8530                   bp++;
8531                   s = indexSet(asmInlineMap, i);
8532                   DEBUGpc("searching symbol s = `%s'", s);
8533                   sym = findSym(SymbolTab, NULL, s);
8534
8535                   if(sym->reqv) {
8536                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8537                   } else {
8538                     strcat(bp1, sym->rname);
8539                   }
8540                   
8541                   while(*bp1)bp1++;
8542               }
8543               
8544               if(strlen(bp1) > cblen - 16) {
8545                 int i = strlen(cbuf);
8546                 cblen += 50;
8547                 cbuf = realloc(cbuf, cblen);
8548                 memset(cbuf+i, 0, 50);
8549                 bp1 = cbuf + i;
8550               }
8551             }
8552             
8553             free(buffer);
8554             buffer = Safe_strdup( cbuf );
8555             free(cbuf);
8556             
8557             bp = bp1 = buffer;
8558         }
8559 #endif  /* 0 */
8560
8561         /* emit each line as a code */
8562         while (*bp) {
8563                 if (*bp == '\n') {
8564                         *bp++ = '\0';
8565
8566                         if(*bp1)
8567                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8568                         bp1 = bp;
8569                 } else {
8570                         if (*bp == ':') {
8571                                 bp++;
8572                                 *bp = '\0';
8573                                 bp++;
8574
8575                                 /* print label, use this special format with NULL directive
8576                                  * to denote that the argument should not be indented with tab */
8577                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8578                                 bp1 = bp;
8579                         } if (*bp == ';') {
8580                                 /* advance to end of line (prevent splitting of comments at ':' */
8581                                 while (*bp && *bp != '\n') {
8582                                         bp++;
8583                                 } // while
8584                         } else
8585                                 bp++;
8586                 }
8587         }
8588
8589         if ((bp1 != bp) && *bp1)
8590                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8591
8592
8593     Safe_free(buffer);
8594
8595     _G.inLine -= (!options.asmpeep);
8596 }
8597
8598 /*-----------------------------------------------------------------*/
8599 /* genRRC - rotate right with carry                                */
8600 /*-----------------------------------------------------------------*/
8601 static void genRRC (iCode *ic)
8602 {
8603   operand *left , *result ;
8604   int size, offset = 0, same;
8605
8606   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8607
8608   /* rotate right with carry */
8609   left = IC_LEFT(ic);
8610   result=IC_RESULT(ic);
8611   pic16_aopOp (left,ic,FALSE);
8612   pic16_aopOp (result,ic,TRUE);
8613
8614   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8615
8616   same = pic16_sameRegs(AOP(result),AOP(left));
8617
8618   size = AOP_SIZE(result);    
8619
8620   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8621
8622   /* get the lsb and put it into the carry */
8623   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8624
8625   offset = 0 ;
8626
8627   while(size--) {
8628
8629     if(same) {
8630       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8631     } else {
8632       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8633       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8634     }
8635
8636     offset++;
8637   }
8638
8639   pic16_freeAsmop(left,NULL,ic,TRUE);
8640   pic16_freeAsmop(result,NULL,ic,TRUE);
8641 }
8642
8643 /*-----------------------------------------------------------------*/
8644 /* genRLC - generate code for rotate left with carry               */
8645 /*-----------------------------------------------------------------*/
8646 static void genRLC (iCode *ic)
8647 {    
8648   operand *left , *result ;
8649   int size, offset = 0;
8650   int same;
8651
8652   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8653   /* rotate right with carry */
8654   left = IC_LEFT(ic);
8655   result=IC_RESULT(ic);
8656   pic16_aopOp (left,ic,FALSE);
8657   pic16_aopOp (result,ic,TRUE);
8658
8659   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8660
8661   same = pic16_sameRegs(AOP(result),AOP(left));
8662
8663   /* move it to the result */
8664   size = AOP_SIZE(result);    
8665
8666   /* get the msb and put it into the carry */
8667   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8668
8669   offset = 0 ;
8670
8671   while(size--) {
8672
8673     if(same) {
8674       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8675     } else {
8676       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8677       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8678     }
8679
8680     offset++;
8681   }
8682
8683
8684   pic16_freeAsmop(left,NULL,ic,TRUE);
8685   pic16_freeAsmop(result,NULL,ic,TRUE);
8686 }
8687
8688
8689 /* gpasm can get the highest order bit with HIGH/UPPER
8690  * so the following probably is not needed -- VR */
8691  
8692 /*-----------------------------------------------------------------*/
8693 /* genGetHbit - generates code get highest order bit               */
8694 /*-----------------------------------------------------------------*/
8695 static void genGetHbit (iCode *ic)
8696 {
8697     operand *left, *result;
8698     left = IC_LEFT(ic);
8699     result=IC_RESULT(ic);
8700     pic16_aopOp (left,ic,FALSE);
8701     pic16_aopOp (result,ic,FALSE);
8702
8703     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8704     /* get the highest order byte into a */
8705     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8706     if(AOP_TYPE(result) == AOP_CRY){
8707         pic16_emitcode("rlc","a");
8708         pic16_outBitC(result);
8709     }
8710     else{
8711         pic16_emitcode("rl","a");
8712         pic16_emitcode("anl","a,#0x01");
8713         pic16_outAcc(result);
8714     }
8715
8716
8717     pic16_freeAsmop(left,NULL,ic,TRUE);
8718     pic16_freeAsmop(result,NULL,ic,TRUE);
8719 }
8720
8721 #if 0
8722 /*-----------------------------------------------------------------*/
8723 /* AccRol - rotate left accumulator by known count                 */
8724 /*-----------------------------------------------------------------*/
8725 static void AccRol (int shCount)
8726 {
8727     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8728     shCount &= 0x0007;              // shCount : 0..7
8729     switch(shCount){
8730         case 0 :
8731             break;
8732         case 1 :
8733             pic16_emitcode("rl","a");
8734             break;
8735         case 2 :
8736             pic16_emitcode("rl","a");
8737             pic16_emitcode("rl","a");
8738             break;
8739         case 3 :
8740             pic16_emitcode("swap","a");
8741             pic16_emitcode("rr","a");
8742             break;
8743         case 4 :
8744             pic16_emitcode("swap","a");
8745             break;
8746         case 5 :
8747             pic16_emitcode("swap","a");
8748             pic16_emitcode("rl","a");
8749             break;
8750         case 6 :
8751             pic16_emitcode("rr","a");
8752             pic16_emitcode("rr","a");
8753             break;
8754         case 7 :
8755             pic16_emitcode("rr","a");
8756             break;
8757     }
8758 }
8759 #endif
8760
8761 /*-----------------------------------------------------------------*/
8762 /* AccLsh - left shift accumulator by known count                  */
8763 /*-----------------------------------------------------------------*/
8764 static void AccLsh (int shCount, int doMask)
8765 {
8766         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8767         switch(shCount){
8768                 case 0 :
8769                         return;
8770                         break;
8771                 case 1 :
8772                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8773                         break;
8774                 case 2 :
8775                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8776                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8777                         break;
8778                 case 3 :
8779                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8780                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8781                         break;
8782                 case 4 :
8783                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8784                         break;
8785                 case 5 :
8786                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8787                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8788                         break;
8789                 case 6 :
8790                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8791                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8792                         break;
8793                 case 7 :
8794                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8795                         break;
8796         }
8797         if (doMask) {
8798                 /* no masking is required in genPackBits */
8799                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8800         }
8801 }
8802
8803 /*-----------------------------------------------------------------*/
8804 /* AccRsh - right shift accumulator by known count                 */
8805 /*-----------------------------------------------------------------*/
8806 static void AccRsh (int shCount, int andmask)
8807 {
8808         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8809         switch(shCount){
8810                 case 0 :
8811                         return; break;
8812                 case 1 :
8813                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8814                         break;
8815                 case 2 :
8816                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8817                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8818                         break;
8819                 case 3 :
8820                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8821                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8822                         break;
8823                 case 4 :
8824                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8825                         break;
8826                 case 5 :
8827                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8828                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8829                         break;
8830                 case 6 :
8831                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8832                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8833                         break;
8834                 case 7 :
8835                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8836                         break;
8837         }
8838         
8839         if(andmask)
8840                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8841         else
8842                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8843 }
8844
8845 #if 0
8846 /*-----------------------------------------------------------------*/
8847 /* AccSRsh - signed right shift accumulator by known count                 */
8848 /*-----------------------------------------------------------------*/
8849 static void AccSRsh (int shCount)
8850 {
8851     symbol *tlbl ;
8852     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8853     if(shCount != 0){
8854         if(shCount == 1){
8855             pic16_emitcode("mov","c,acc.7");
8856             pic16_emitcode("rrc","a");
8857         } else if(shCount == 2){
8858             pic16_emitcode("mov","c,acc.7");
8859             pic16_emitcode("rrc","a");
8860             pic16_emitcode("mov","c,acc.7");
8861             pic16_emitcode("rrc","a");
8862         } else {
8863             tlbl = newiTempLabel(NULL);
8864             /* rotate right accumulator */
8865             AccRol(8 - shCount);
8866             /* and kill the higher order bits */
8867             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8868             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8869             pic16_emitcode("orl","a,#0x%02x",
8870                      (unsigned char)~SRMask[shCount]);
8871             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8872         }
8873     }
8874 }
8875 #endif
8876
8877 /*-----------------------------------------------------------------*/
8878 /* shiftR1Left2Result - shift right one byte from left to result   */
8879 /*-----------------------------------------------------------------*/
8880 static void shiftR1Left2ResultSigned (operand *left, int offl,
8881                                 operand *result, int offr,
8882                                 int shCount)
8883 {
8884   int same;
8885
8886   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8887
8888   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8889
8890   switch(shCount) {
8891   case 1:
8892     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8893     if(same) 
8894       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8895     else {
8896       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8897       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8898     }
8899
8900     break;
8901   case 2:
8902
8903     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8904     if(same) 
8905       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8906     else {
8907       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8908       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8909     }
8910     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8911     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8912
8913     break;
8914
8915   case 3:
8916     if(same)
8917       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8918     else {
8919       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8920       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8921     }
8922
8923     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8924     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8925     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8926
8927     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8928     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8929
8930     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8931     break;
8932
8933   case 4:
8934     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8935     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8936     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8937     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8938     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8939     break;
8940   case 5:
8941     if(same) {
8942       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8943     } else {
8944       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8945       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8946     }
8947     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8948     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8949     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8950     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8951     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8952     break;
8953
8954   case 6:
8955     if(same) {
8956       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8957       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8958       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8959       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8960       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8961       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8962     } else {
8963       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8964       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8965       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8966       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8967       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8968     }
8969     break;
8970
8971   case 7:
8972     if(same) {
8973       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8974       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8975       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8976       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8977     } else {
8978       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8979       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8980       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8981     }
8982
8983   default:
8984     break;
8985   }
8986 }
8987
8988 /*-----------------------------------------------------------------*/
8989 /* shiftR1Left2Result - shift right one byte from left to result   */
8990 /*-----------------------------------------------------------------*/
8991 static void shiftR1Left2Result (operand *left, int offl,
8992                                 operand *result, int offr,
8993                                 int shCount, int sign)
8994 {
8995   int same;
8996
8997   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8998
8999   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9000
9001   /* Copy the msb into the carry if signed. */
9002   if(sign) {
9003     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9004     return;
9005   }
9006
9007
9008
9009   switch(shCount) {
9010   case 1:
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     break;
9019   case 2:
9020     emitCLRC;
9021     if(same) {
9022       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9023     } else {
9024       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9025       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9026     }
9027     emitCLRC;
9028     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9029
9030     break;
9031   case 3:
9032     if(same)
9033       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9034     else {
9035       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9036       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9037     }
9038
9039     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9040     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9041     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9042     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9043     break;
9044       
9045   case 4:
9046     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9047     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9048     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9049     break;
9050
9051   case 5:
9052     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9053     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9054     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9055     //emitCLRC;
9056     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9057
9058     break;
9059   case 6:
9060
9061     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9062     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9063     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9064     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9065     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9066     break;
9067
9068   case 7:
9069
9070     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9071     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9072     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9073
9074     break;
9075
9076   default:
9077     break;
9078   }
9079 }
9080
9081 /*-----------------------------------------------------------------*/
9082 /* shiftL1Left2Result - shift left one byte from left to result    */
9083 /*-----------------------------------------------------------------*/
9084 static void shiftL1Left2Result (operand *left, int offl,
9085                                 operand *result, int offr, int shCount)
9086 {
9087   int same;
9088
9089   //    char *l;
9090   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9091
9092   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9093   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9094     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9095     //    MOVA(l);
9096     /* shift left accumulator */
9097     //AccLsh(shCount, 1); // don't comment out just yet...
9098   //    pic16_aopPut(AOP(result),"a",offr);
9099
9100   switch(shCount) {
9101   case 1:
9102     /* Shift left 1 bit position */
9103     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9104     if(same) {
9105       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9106     } else {
9107       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9108       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9109     }
9110     break;
9111   case 2:
9112     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9113     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9114     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9115     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9116     break;
9117   case 3:
9118     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9119     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9120     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9121     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9122     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9123     break;
9124   case 4:
9125     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9126     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9127     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9128     break;
9129   case 5:
9130     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9131     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9132     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9133     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9134     break;
9135   case 6:
9136     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9137     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9138     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9139     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9140     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9141     break;
9142   case 7:
9143     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9144     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9145     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9146     break;
9147
9148   default:
9149     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9150   }
9151
9152 }
9153
9154 /*-----------------------------------------------------------------*/
9155 /* movLeft2Result - move byte from left to result                  */
9156 /*-----------------------------------------------------------------*/
9157 static void movLeft2Result (operand *left, int offl,
9158                             operand *result, int offr)
9159 {
9160   char *l;
9161   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9162   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9163     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9164
9165     if (*l == '@' && (IS_AOP_PREG(result))) {
9166       pic16_emitcode("mov","a,%s",l);
9167       pic16_aopPut(AOP(result),"a",offr);
9168     } else {
9169       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9170       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9171     }
9172   }
9173 }
9174
9175 /*-----------------------------------------------------------------*/
9176 /* shiftL2Left2Result - shift left two bytes from left to result   */
9177 /*-----------------------------------------------------------------*/
9178 static void shiftL2Left2Result (operand *left, int offl,
9179                                 operand *result, int offr, int shCount)
9180 {
9181   int same = pic16_sameRegs(AOP(result), AOP(left));
9182   int i;
9183
9184   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9185
9186   if (same && (offl != offr)) { // shift bytes
9187     if (offr > offl) {
9188        for(i=1;i>-1;i--) {
9189          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9190          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9191        }
9192     } else { // just treat as different later on
9193                 same = 0;
9194     }
9195   }
9196
9197   if(same) {
9198     switch(shCount) {
9199     case 0:
9200       break;
9201     case 1:
9202     case 2:
9203     case 3:
9204
9205       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9206       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9207       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9208
9209       while(--shCount) {
9210                 emitCLRC;
9211                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9212                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9213       }
9214
9215       break;
9216     case 4:
9217     case 5:
9218       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9219       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9220       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9221       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9222       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9223       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9224       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9225       if(shCount >=5) {
9226                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9227                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9228       }
9229       break;
9230     case 6:
9231       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9232       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9233       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9234       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9235       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9236       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9237       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9238       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9239       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9240       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9241       break;
9242     case 7:
9243       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9244       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9245       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9246       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9247       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9248     }
9249
9250   } else {
9251     switch(shCount) {
9252     case 0:
9253       break;
9254     case 1:
9255     case 2:
9256     case 3:
9257       /* note, use a mov/add for the shift since the mov has a
9258          chance of getting optimized out */
9259       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9260       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9261       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9262       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9263       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9264
9265       while(--shCount) {
9266                 emitCLRC;
9267                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9268                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9269       }
9270       break;
9271
9272     case 4:
9273     case 5:
9274       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9275       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9276       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9277       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9278       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9279       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9280       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9281       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9282
9283
9284       if(shCount == 5) {
9285                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9286                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9287       }
9288       break;
9289     case 6:
9290       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9291       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9292       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9293       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9294
9295       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9296       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9297       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9298       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9299       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9300       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9301       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9302       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9303       break;
9304     case 7:
9305       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9306       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9307       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9308       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9309       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9310     }
9311   }
9312
9313 }
9314 /*-----------------------------------------------------------------*/
9315 /* shiftR2Left2Result - shift right two bytes from left to result  */
9316 /*-----------------------------------------------------------------*/
9317 static void shiftR2Left2Result (operand *left, int offl,
9318                                 operand *result, int offr,
9319                                 int shCount, int sign)
9320 {
9321   int same = pic16_sameRegs(AOP(result), AOP(left));
9322   int i;
9323   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9324
9325   if (same && (offl != offr)) { // shift right bytes
9326     if (offr < offl) {
9327        for(i=0;i<2;i++) {
9328          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9329          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9330        }
9331     } else { // just treat as different later on
9332                 same = 0;
9333     }
9334   }
9335
9336   switch(shCount) {
9337   case 0:
9338     break;
9339   case 1:
9340   case 2:
9341   case 3:
9342     /* obtain sign from left operand */
9343     if(sign)
9344       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9345     else
9346       emitCLRC;
9347
9348     if(same) {
9349       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9350       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9351     } else {
9352       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9353       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9354       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9355       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9356     }
9357
9358     while(--shCount) {
9359       if(sign)
9360         /* now get sign from already assigned result (avoid BANKSEL) */
9361         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9362       else
9363         emitCLRC;
9364       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9365       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9366     }
9367     break;
9368   case 4:
9369   case 5:
9370     if(same) {
9371
9372       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9373       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9374       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9375
9376       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9377       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9378       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9379       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9380     } else {
9381       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9382       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9383       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9384
9385       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9386       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9387       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9388       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9389       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9390     }
9391
9392     if(shCount >=5) {
9393       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9394       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9395     }
9396
9397     if(sign) {
9398       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9399       pic16_emitpcode(POC_BTFSC, 
9400                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9401       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9402     }
9403
9404     break;
9405
9406   case 6:
9407     if(same) {
9408
9409       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9410       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9411
9412       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9413       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9414       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9415       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9416       if(sign) {
9417         pic16_emitpcode(POC_BTFSC, 
9418                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9419         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9420       }
9421       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9422       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9423       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9424       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9425     } else {
9426       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9427       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9428       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9429       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9430       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9431       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9432       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9433       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9434       if(sign) {
9435         pic16_emitpcode(POC_BTFSC, 
9436                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9437         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9438       }
9439       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9440       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9441
9442         
9443     }
9444
9445     break;
9446   case 7:
9447     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9448     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9449     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9450     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9451     if(sign) {
9452       emitSKPNC;
9453       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9454     } else 
9455       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9456   }
9457 }
9458
9459
9460 /*-----------------------------------------------------------------*/
9461 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9462 /*-----------------------------------------------------------------*/
9463 static void shiftLLeftOrResult (operand *left, int offl,
9464                                 operand *result, int offr, int shCount)
9465 {
9466     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9467
9468     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9469     /* shift left accumulator */
9470     AccLsh(shCount, 1);
9471     /* or with result */
9472     /* back to result */
9473     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9474 }
9475
9476 /*-----------------------------------------------------------------*/
9477 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9478 /*-----------------------------------------------------------------*/
9479 static void shiftRLeftOrResult (operand *left, int offl,
9480                                 operand *result, int offr, int shCount)
9481 {
9482     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9483     
9484     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9485     /* shift right accumulator */
9486     AccRsh(shCount, 1);
9487     /* or with result */
9488     /* back to result */
9489     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9490 }
9491
9492 /*-----------------------------------------------------------------*/
9493 /* genlshOne - left shift a one byte quantity by known count       */
9494 /*-----------------------------------------------------------------*/
9495 static void genlshOne (operand *result, operand *left, int shCount)
9496 {       
9497     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9498     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9499 }
9500
9501 /*-----------------------------------------------------------------*/
9502 /* genlshTwo - left shift two bytes by known amount != 0           */
9503 /*-----------------------------------------------------------------*/
9504 static void genlshTwo (operand *result,operand *left, int shCount)
9505 {
9506     int size;
9507     
9508     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9509     size = pic16_getDataSize(result);
9510
9511     /* if shCount >= 8 */
9512     if (shCount >= 8) {
9513         shCount -= 8 ;
9514
9515         if (size > 1){
9516             if (shCount)
9517                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9518             else 
9519                 movLeft2Result(left, LSB, result, MSB16);
9520         }
9521         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9522     }
9523
9524     /*  1 <= shCount <= 7 */
9525     else {  
9526         if(size == 1)
9527             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9528         else 
9529             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9530     }
9531 }
9532
9533 /*-----------------------------------------------------------------*/
9534 /* shiftLLong - shift left one long from left to result            */
9535 /* offr = LSB or MSB16                                             */
9536 /*-----------------------------------------------------------------*/
9537 static void shiftLLong (operand *left, operand *result, int offr )
9538 {
9539     int size = AOP_SIZE(result);
9540     int same = pic16_sameRegs(AOP(left),AOP(result));
9541         int i;
9542
9543     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9544
9545         if (same && (offr == MSB16)) { //shift one byte
9546                 for(i=size-1;i>=MSB16;i--) {
9547                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9548                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9549                 }
9550         } else {
9551                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9552         }
9553         
9554     if (size > LSB+offr ){
9555                 if (same) {
9556                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9557                 } else {
9558                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9559                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9560                 }
9561          }
9562
9563     if(size > MSB16+offr){
9564                 if (same) {
9565                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9566                 } else {
9567                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9568                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9569                 }
9570     }
9571
9572     if(size > MSB24+offr){
9573                 if (same) {
9574                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9575                 } else {
9576                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9577                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9578                 }
9579     }
9580
9581     if(size > MSB32+offr){
9582                 if (same) {
9583                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9584                 } else {
9585                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9586                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9587                 }
9588     }
9589     if(offr != LSB)
9590                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9591
9592 }
9593
9594 /*-----------------------------------------------------------------*/
9595 /* genlshFour - shift four byte by a known amount != 0             */
9596 /*-----------------------------------------------------------------*/
9597 static void genlshFour (operand *result, operand *left, int shCount)
9598 {
9599     int size;
9600
9601     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9602     size = AOP_SIZE(result);
9603
9604     /* if shifting more that 3 bytes */
9605     if (shCount >= 24 ) {
9606         shCount -= 24;
9607         if (shCount)
9608             /* lowest order of left goes to the highest
9609             order of the destination */
9610             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9611         else
9612             movLeft2Result(left, LSB, result, MSB32);
9613
9614                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9615                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9616                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9617
9618         return;
9619     }
9620
9621     /* more than two bytes */
9622     else if ( shCount >= 16 ) {
9623         /* lower order two bytes goes to higher order two bytes */
9624         shCount -= 16;
9625         /* if some more remaining */
9626         if (shCount)
9627             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9628         else {
9629             movLeft2Result(left, MSB16, result, MSB32);
9630             movLeft2Result(left, LSB, result, MSB24);
9631         }
9632                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9633                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9634         return;
9635     }    
9636
9637     /* if more than 1 byte */
9638     else if ( shCount >= 8 ) {
9639         /* lower order three bytes goes to higher order  three bytes */
9640         shCount -= 8;
9641         if(size == 2){
9642             if(shCount)
9643                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9644             else
9645                 movLeft2Result(left, LSB, result, MSB16);
9646         }
9647         else{   /* size = 4 */
9648             if(shCount == 0){
9649                 movLeft2Result(left, MSB24, result, MSB32);
9650                 movLeft2Result(left, MSB16, result, MSB24);
9651                 movLeft2Result(left, LSB, result, MSB16);
9652                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9653             }
9654             else if(shCount == 1)
9655                 shiftLLong(left, result, MSB16);
9656             else{
9657                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9658                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9659                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9660                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9661             }
9662         }
9663     }
9664
9665     /* 1 <= shCount <= 7 */
9666     else if(shCount <= 3)
9667     { 
9668         shiftLLong(left, result, LSB);
9669         while(--shCount >= 1)
9670             shiftLLong(result, result, LSB);
9671     }
9672     /* 3 <= shCount <= 7, optimize */
9673     else{
9674         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9675         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9676         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9677     }
9678 }
9679
9680 /*-----------------------------------------------------------------*/
9681 /* genLeftShiftLiteral - left shifting by known count              */
9682 /*-----------------------------------------------------------------*/
9683 void pic16_genLeftShiftLiteral (operand *left,
9684                                  operand *right,
9685                                  operand *result,
9686                                  iCode *ic)
9687 {    
9688     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9689     int size;
9690
9691     FENTRY;
9692     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9693     pic16_freeAsmop(right,NULL,ic,TRUE);
9694
9695     pic16_aopOp(left,ic,FALSE);
9696     pic16_aopOp(result,ic,TRUE);
9697
9698     size = getSize(operandType(result));
9699
9700 #if VIEW_SIZE
9701     pic16_emitcode("; shift left ","result %d, left %d",size,
9702              AOP_SIZE(left));
9703 #endif
9704
9705     /* I suppose that the left size >= result size */
9706     if(shCount == 0){
9707         while(size--){
9708             movLeft2Result(left, size, result, size);
9709         }
9710     }
9711
9712     else if(shCount >= (size * 8))
9713         while(size--)
9714             pic16_aopPut(AOP(result),zero,size);
9715     else{
9716         switch (size) {
9717             case 1:
9718                 genlshOne (result,left,shCount);
9719                 break;
9720
9721             case 2:
9722             case 3:
9723                 genlshTwo (result,left,shCount);
9724                 break;
9725
9726             case 4:
9727                 genlshFour (result,left,shCount);
9728                 break;
9729         }
9730     }
9731     pic16_freeAsmop(left,NULL,ic,TRUE);
9732     pic16_freeAsmop(result,NULL,ic,TRUE);
9733 }
9734
9735 /*-----------------------------------------------------------------*
9736  * genMultiAsm - repeat assembly instruction for size of register.
9737  * if endian == 1, then the high byte (i.e base address + size of 
9738  * register) is used first else the low byte is used first;
9739  *-----------------------------------------------------------------*/
9740 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9741 {
9742
9743   int offset = 0;
9744
9745   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9746
9747   if(!reg)
9748     return;
9749
9750   if(!endian) {
9751     endian = 1;
9752   } else {
9753     endian = -1;
9754     offset = size-1;
9755   }
9756
9757   while(size--) {
9758     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9759     offset += endian;
9760   }
9761
9762 }
9763
9764 #if !(USE_GENERIC_SIGNED_SHIFT)
9765 /*-----------------------------------------------------------------*/
9766 /* genLeftShift - generates code for left shifting                 */
9767 /*-----------------------------------------------------------------*/
9768 static void genLeftShift (iCode *ic)
9769 {
9770   operand *left,*right, *result;
9771   int size, offset;
9772 //  char *l;
9773   symbol *tlbl , *tlbl1;
9774   pCodeOp *pctemp;
9775
9776   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9777
9778   right = IC_RIGHT(ic);
9779   left  = IC_LEFT(ic);
9780   result = IC_RESULT(ic);
9781
9782   pic16_aopOp(right,ic,FALSE);
9783
9784   /* if the shift count is known then do it 
9785      as efficiently as possible */
9786   if (AOP_TYPE(right) == AOP_LIT) {
9787     pic16_genLeftShiftLiteral (left,right,result,ic);
9788     return ;
9789   }
9790
9791   /* shift count is unknown then we have to form
9792    * a loop. Get the loop count in WREG : Note: we take
9793    * only the lower order byte since shifting
9794    * more than 32 bits make no sense anyway, ( the
9795    * largest size of an object can be only 32 bits ) */
9796   
9797   pic16_aopOp(left,ic,FALSE);
9798   pic16_aopOp(result,ic,FALSE);
9799
9800   /* now move the left to the result if they are not the
9801    * same, and if size > 1,
9802    * and if right is not same to result (!!!) -- VR */
9803   if (!pic16_sameRegs(AOP(left),AOP(result))
9804       && (AOP_SIZE(result) > 1)) {
9805
9806     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9807
9808     size = AOP_SIZE(result);
9809     offset=0;
9810     while (size--) {
9811
9812 #if 0
9813       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9814       if (*l == '@' && (IS_AOP_PREG(result))) {
9815
9816           pic16_emitcode("mov","a,%s",l);
9817           pic16_aopPut(AOP(result),"a",offset);
9818       } else
9819 #endif
9820       {
9821         /* we don't know if left is a literal or a register, take care -- VR */
9822         pic16_mov2f(AOP(result), AOP(left), offset);
9823       }
9824       offset++;
9825     }
9826   }
9827
9828   size = AOP_SIZE(result);
9829
9830   /* if it is only one byte then */
9831   if (size == 1) {
9832     if(optimized_for_speed) {
9833       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9834       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9835       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9836       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9837       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9838       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9839       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9840       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9841       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9842       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9843       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9844       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9845     } else {
9846
9847       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9848
9849       tlbl = newiTempLabel(NULL);
9850
9851 #if 1
9852       /* this is already done, why change it? */
9853       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9854                 pic16_mov2f(AOP(result), AOP(left), 0);
9855       }
9856 #endif
9857
9858       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9859       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9860       pic16_emitpLabel(tlbl->key);
9861       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9862       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9863       emitSKPC;
9864       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9865     }
9866     goto release ;
9867   }
9868     
9869   if (pic16_sameRegs(AOP(left),AOP(result))) {
9870
9871     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9872     
9873     tlbl = newiTempLabel(NULL);
9874     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9875     genMultiAsm(POC_RRCF, result, size,1);
9876     pic16_emitpLabel(tlbl->key);
9877     genMultiAsm(POC_RLCF, result, size,0);
9878     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9879     emitSKPC;
9880     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9881     goto release;
9882   }
9883
9884   //tlbl = newiTempLabel(NULL);
9885   //offset = 0 ;   
9886   //tlbl1 = newiTempLabel(NULL);
9887
9888   //reAdjustPreg(AOP(result));    
9889     
9890   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9891   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9892   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9893   //MOVA(l);
9894   //pic16_emitcode("add","a,acc");         
9895   //pic16_aopPut(AOP(result),"a",offset++);
9896   //while (--size) {
9897   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9898   //  MOVA(l);
9899   //  pic16_emitcode("rlc","a");         
9900   //  pic16_aopPut(AOP(result),"a",offset++);
9901   //}
9902   //reAdjustPreg(AOP(result));
9903
9904   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9905   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9906
9907
9908   tlbl = newiTempLabel(NULL);
9909   tlbl1= newiTempLabel(NULL);
9910
9911   size = AOP_SIZE(result);
9912   offset = 1;
9913
9914   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9915
9916   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9917
9918   /* offset should be 0, 1 or 3 */
9919   
9920   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9921   emitSKPNZ;
9922   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9923
9924   pic16_emitpcode(POC_MOVWF, pctemp);
9925
9926
9927   pic16_emitpLabel(tlbl->key);
9928
9929   emitCLRC;
9930   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9931   while(--size)
9932     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9933
9934   pic16_emitpcode(POC_DECFSZ,  pctemp);
9935   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9936   pic16_emitpLabel(tlbl1->key);
9937
9938   pic16_popReleaseTempReg(pctemp,1);
9939
9940
9941  release:
9942   pic16_freeAsmop (right,NULL,ic,TRUE);
9943   pic16_freeAsmop(left,NULL,ic,TRUE);
9944   pic16_freeAsmop(result,NULL,ic,TRUE);
9945 }
9946 #endif
9947
9948
9949 #if 0
9950 #error old code (left here for reference)
9951 /*-----------------------------------------------------------------*/
9952 /* genLeftShift - generates code for left shifting                 */
9953 /*-----------------------------------------------------------------*/
9954 static void genLeftShift (iCode *ic)
9955 {
9956   operand *left,*right, *result;
9957   int size, offset;
9958   char *l;
9959   symbol *tlbl , *tlbl1;
9960   pCodeOp *pctemp;
9961
9962   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9963
9964   right = IC_RIGHT(ic);
9965   left  = IC_LEFT(ic);
9966   result = IC_RESULT(ic);
9967
9968   pic16_aopOp(right,ic,FALSE);
9969
9970   /* if the shift count is known then do it 
9971      as efficiently as possible */
9972   if (AOP_TYPE(right) == AOP_LIT) {
9973     pic16_genLeftShiftLiteral (left,right,result,ic);
9974     return ;
9975   }
9976
9977   /* shift count is unknown then we have to form 
9978      a loop get the loop count in B : Note: we take
9979      only the lower order byte since shifting
9980      more that 32 bits make no sense anyway, ( the
9981      largest size of an object can be only 32 bits ) */  
9982
9983     
9984   pic16_aopOp(left,ic,FALSE);
9985   pic16_aopOp(result,ic,FALSE);
9986
9987   /* now move the left to the result if they are not the
9988      same */
9989   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9990       AOP_SIZE(result) > 1) {
9991
9992     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9993
9994     size = AOP_SIZE(result);
9995     offset=0;
9996     while (size--) {
9997       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9998       if (*l == '@' && (IS_AOP_PREG(result))) {
9999
10000         pic16_emitcode("mov","a,%s",l);
10001         pic16_aopPut(AOP(result),"a",offset);
10002       } else {
10003
10004         /* we don't know if left is a literal or a register, take care -- VR */
10005         pic16_mov2f(AOP(result), AOP(left), offset);
10006       }
10007       offset++;
10008     }
10009   }
10010
10011   size = AOP_SIZE(result);
10012
10013   /* if it is only one byte then */
10014   if (size == 1) {
10015     if(optimized_for_speed) {
10016       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10017       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10018       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10019       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10020       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10021       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10022       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10023       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10024       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10025       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10026       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10027       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10028     } else {
10029
10030       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10031
10032       tlbl = newiTempLabel(NULL);
10033       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10034                 pic16_mov2f(AOP(result), AOP(left), 0);
10035                 
10036 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10037 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10038       }
10039
10040       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10041       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10042       pic16_emitpLabel(tlbl->key);
10043       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10044       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10045       emitSKPC;
10046       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10047     }
10048     goto release ;
10049   }
10050     
10051   if (pic16_sameRegs(AOP(left),AOP(result))) {
10052
10053     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10054     
10055     tlbl = newiTempLabel(NULL);
10056     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10057     genMultiAsm(POC_RRCF, result, size,1);
10058     pic16_emitpLabel(tlbl->key);
10059     genMultiAsm(POC_RLCF, result, size,0);
10060     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10061     emitSKPC;
10062     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10063     goto release;
10064   }
10065
10066   //tlbl = newiTempLabel(NULL);
10067   //offset = 0 ;   
10068   //tlbl1 = newiTempLabel(NULL);
10069
10070   //reAdjustPreg(AOP(result));    
10071     
10072   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10073   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10074   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10075   //MOVA(l);
10076   //pic16_emitcode("add","a,acc");         
10077   //pic16_aopPut(AOP(result),"a",offset++);
10078   //while (--size) {
10079   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10080   //  MOVA(l);
10081   //  pic16_emitcode("rlc","a");         
10082   //  pic16_aopPut(AOP(result),"a",offset++);
10083   //}
10084   //reAdjustPreg(AOP(result));
10085
10086   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10087   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10088
10089
10090   tlbl = newiTempLabel(NULL);
10091   tlbl1= newiTempLabel(NULL);
10092
10093   size = AOP_SIZE(result);
10094   offset = 1;
10095
10096   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10097
10098   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10099
10100   /* offset should be 0, 1 or 3 */
10101   
10102   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10103   emitSKPNZ;
10104   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10105
10106   pic16_emitpcode(POC_MOVWF, pctemp);
10107
10108
10109   pic16_emitpLabel(tlbl->key);
10110
10111   emitCLRC;
10112   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10113   while(--size)
10114     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10115
10116   pic16_emitpcode(POC_DECFSZ,  pctemp);
10117   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10118   pic16_emitpLabel(tlbl1->key);
10119
10120   pic16_popReleaseTempReg(pctemp,1);
10121
10122
10123  release:
10124   pic16_freeAsmop (right,NULL,ic,TRUE);
10125   pic16_freeAsmop(left,NULL,ic,TRUE);
10126   pic16_freeAsmop(result,NULL,ic,TRUE);
10127 }
10128 #endif
10129
10130 /*-----------------------------------------------------------------*/
10131 /* genrshOne - right shift a one byte quantity by known count      */
10132 /*-----------------------------------------------------------------*/
10133 static void genrshOne (operand *result, operand *left,
10134                        int shCount, int sign)
10135 {
10136     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10137     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10138 }
10139
10140 /*-----------------------------------------------------------------*/
10141 /* genrshTwo - right shift two bytes by known amount != 0          */
10142 /*-----------------------------------------------------------------*/
10143 static void genrshTwo (operand *result,operand *left,
10144                        int shCount, int sign)
10145 {
10146   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10147   /* if shCount >= 8 */
10148   if (shCount >= 8) {
10149     shCount -= 8 ;
10150     if (shCount)
10151       shiftR1Left2Result(left, MSB16, result, LSB,
10152                          shCount, sign);
10153     else
10154       movLeft2Result(left, MSB16, result, LSB);
10155
10156     pic16_addSign (result, 1, sign);
10157   }
10158
10159   /*  1 <= shCount <= 7 */
10160   else
10161     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10162 }
10163
10164 /*-----------------------------------------------------------------*/
10165 /* shiftRLong - shift right one long from left to result           */
10166 /* offl = LSB or MSB16                                             */
10167 /*-----------------------------------------------------------------*/
10168 static void shiftRLong (operand *left, int offl,
10169                         operand *result, int sign)
10170 {
10171     int size = AOP_SIZE(result);
10172     int same = pic16_sameRegs(AOP(left),AOP(result));
10173     int i;
10174     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10175
10176         if (same && (offl == MSB16)) { //shift one byte right
10177                 for(i=MSB16;i<size;i++) {
10178                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10179                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10180                 }
10181         }
10182
10183     if(sign)
10184                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10185         else
10186                 emitCLRC;
10187
10188         if (same) {
10189                 if (offl == LSB)
10190                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10191         } else {
10192         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10193         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10194         }
10195
10196     if(offl == MSB16) {
10197         /* add sign of "a" */
10198         pic16_addSign(result, MSB32, sign);
10199         }
10200
10201         if (same) {
10202         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10203         } else {
10204         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10205         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10206         }
10207         
10208         if (same) {
10209         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10210         } else {
10211         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10212         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10213         }
10214
10215         if (same) {
10216         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10217         } else {
10218         if(offl == LSB){
10219                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10220                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10221         }
10222         }
10223 }
10224
10225 /*-----------------------------------------------------------------*/
10226 /* genrshFour - shift four byte by a known amount != 0             */
10227 /*-----------------------------------------------------------------*/
10228 static void genrshFour (operand *result, operand *left,
10229                         int shCount, int sign)
10230 {
10231   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10232   /* if shifting more that 3 bytes */
10233   if(shCount >= 24 ) {
10234     shCount -= 24;
10235     if(shCount)
10236       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10237     else
10238       movLeft2Result(left, MSB32, result, LSB);
10239
10240     pic16_addSign(result, MSB16, sign);
10241   }
10242   else if(shCount >= 16){
10243     shCount -= 16;
10244     if(shCount)
10245       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10246     else{
10247       movLeft2Result(left, MSB24, result, LSB);
10248       movLeft2Result(left, MSB32, result, MSB16);
10249     }
10250     pic16_addSign(result, MSB24, sign);
10251   }
10252   else if(shCount >= 8){
10253     shCount -= 8;
10254     if(shCount == 1)
10255       shiftRLong(left, MSB16, result, sign);
10256     else if(shCount == 0){
10257       movLeft2Result(left, MSB16, result, LSB);
10258       movLeft2Result(left, MSB24, result, MSB16);
10259       movLeft2Result(left, MSB32, result, MSB24);
10260       pic16_addSign(result, MSB32, sign);
10261     }
10262     else{ //shcount >= 2
10263       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10264       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10265       /* the last shift is signed */
10266       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10267       pic16_addSign(result, MSB32, sign);
10268     }
10269   }
10270   else{   /* 1 <= shCount <= 7 */
10271     if(shCount <= 2){
10272       shiftRLong(left, LSB, result, sign);
10273       if(shCount == 2)
10274         shiftRLong(result, LSB, result, sign);
10275     }
10276     else{
10277       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10278       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10279       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10280     }
10281   }
10282 }
10283
10284 /*-----------------------------------------------------------------*/
10285 /* genRightShiftLiteral - right shifting by known count            */
10286 /*-----------------------------------------------------------------*/
10287 static void genRightShiftLiteral (operand *left,
10288                                   operand *right,
10289                                   operand *result,
10290                                   iCode *ic,
10291                                   int sign)
10292 {    
10293   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10294   int lsize,res_size;
10295
10296   pic16_freeAsmop(right,NULL,ic,TRUE);
10297
10298   pic16_aopOp(left,ic,FALSE);
10299   pic16_aopOp(result,ic,TRUE);
10300
10301   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10302
10303 #if VIEW_SIZE
10304   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10305                  AOP_SIZE(left));
10306 #endif
10307
10308   lsize = pic16_getDataSize(left);
10309   res_size = pic16_getDataSize(result);
10310   /* test the LEFT size !!! */
10311
10312   /* I suppose that the left size >= result size */
10313   if(shCount == 0){
10314     assert (res_size <= lsize);
10315     while (res_size--) {
10316       pic16_mov2f (AOP(result), AOP(left), res_size);
10317     } // for
10318   }
10319
10320   else if(shCount >= (lsize * 8)){
10321
10322     if(res_size == 1) {
10323       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10324       if(sign) {
10325         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10326         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10327       }
10328     } else {
10329
10330       if(sign) {
10331         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10332         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10333         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10334         while(res_size--)
10335           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10336
10337       } else {
10338
10339         while(res_size--)
10340           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10341       }
10342     }
10343   } else {
10344
10345     switch (res_size) {
10346     case 1:
10347       genrshOne (result,left,shCount,sign);
10348       break;
10349
10350     case 2:
10351       genrshTwo (result,left,shCount,sign);
10352       break;
10353
10354     case 4:
10355       genrshFour (result,left,shCount,sign);
10356       break;
10357     default :
10358       break;
10359     }
10360
10361   }
10362
10363   pic16_freeAsmop(left,NULL,ic,TRUE);
10364   pic16_freeAsmop(result,NULL,ic,TRUE);
10365 }
10366
10367 #if !(USE_GENERIC_SIGNED_SHIFT)
10368 /*-----------------------------------------------------------------*/
10369 /* genSignedRightShift - right shift of signed number              */
10370 /*-----------------------------------------------------------------*/
10371 static void genSignedRightShift (iCode *ic)
10372 {
10373   operand *right, *left, *result;
10374   int size, offset;
10375   //  char *l;
10376   symbol *tlbl, *tlbl1 ;
10377   pCodeOp *pctemp;
10378
10379   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10380
10381   /* we do it the hard way put the shift count in b
10382      and loop thru preserving the sign */
10383   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10384
10385   right = IC_RIGHT(ic);
10386   left  = IC_LEFT(ic);
10387   result = IC_RESULT(ic);
10388
10389   pic16_aopOp(right,ic,FALSE);  
10390   pic16_aopOp(left,ic,FALSE);
10391   pic16_aopOp(result,ic,FALSE);
10392
10393
10394   if ( AOP_TYPE(right) == AOP_LIT) {
10395     genRightShiftLiteral (left,right,result,ic,1);
10396     return ;
10397   }
10398   /* shift count is unknown then we have to form 
10399      a loop get the loop count in B : Note: we take
10400      only the lower order byte since shifting
10401      more that 32 bits make no sense anyway, ( the
10402      largest size of an object can be only 32 bits ) */  
10403
10404   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10405   //pic16_emitcode("inc","b");
10406   //pic16_freeAsmop (right,NULL,ic,TRUE);
10407   //pic16_aopOp(left,ic,FALSE);
10408   //pic16_aopOp(result,ic,FALSE);
10409
10410   /* now move the left to the result if they are not the
10411      same */
10412   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10413       AOP_SIZE(result) > 1) {
10414
10415     size = AOP_SIZE(result);
10416     offset=0;
10417     while (size--) { 
10418       /*
10419         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10420         if (*l == '@' && IS_AOP_PREG(result)) {
10421
10422         pic16_emitcode("mov","a,%s",l);
10423         pic16_aopPut(AOP(result),"a",offset);
10424         } else
10425         pic16_aopPut(AOP(result),l,offset);
10426       */
10427       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10428       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10429
10430       offset++;
10431     }
10432   }
10433
10434   /* mov the highest order bit to OVR */    
10435   tlbl = newiTempLabel(NULL);
10436   tlbl1= newiTempLabel(NULL);
10437
10438   size = AOP_SIZE(result);
10439   offset = size - 1;
10440
10441   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10442
10443   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10444
10445   /* offset should be 0, 1 or 3 */
10446   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10447   emitSKPNZ;
10448   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10449
10450   pic16_emitpcode(POC_MOVWF, pctemp);
10451
10452
10453   pic16_emitpLabel(tlbl->key);
10454
10455   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10456   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10457
10458   while(--size) {
10459     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10460   }
10461
10462   pic16_emitpcode(POC_DECFSZ,  pctemp);
10463   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10464   pic16_emitpLabel(tlbl1->key);
10465
10466   pic16_popReleaseTempReg(pctemp,1);
10467 #if 0
10468   size = AOP_SIZE(result);
10469   offset = size - 1;
10470   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10471   pic16_emitcode("rlc","a");
10472   pic16_emitcode("mov","ov,c");
10473   /* if it is only one byte then */
10474   if (size == 1) {
10475     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10476     MOVA(l);
10477     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10478     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10479     pic16_emitcode("mov","c,ov");
10480     pic16_emitcode("rrc","a");
10481     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10482     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10483     pic16_aopPut(AOP(result),"a",0);
10484     goto release ;
10485   }
10486
10487   reAdjustPreg(AOP(result));
10488   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10489   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10490   pic16_emitcode("mov","c,ov");
10491   while (size--) {
10492     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10493     MOVA(l);
10494     pic16_emitcode("rrc","a");         
10495     pic16_aopPut(AOP(result),"a",offset--);
10496   }
10497   reAdjustPreg(AOP(result));
10498   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10499   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10500
10501  release:
10502 #endif
10503
10504   pic16_freeAsmop(left,NULL,ic,TRUE);
10505   pic16_freeAsmop(result,NULL,ic,TRUE);
10506   pic16_freeAsmop(right,NULL,ic,TRUE);
10507 }
10508 #endif
10509
10510 #if !(USE_GENERIC_SIGNED_SHIFT)
10511 #warning This implementation of genRightShift() is incomplete!
10512 /*-----------------------------------------------------------------*/
10513 /* genRightShift - generate code for right shifting                */
10514 /*-----------------------------------------------------------------*/
10515 static void genRightShift (iCode *ic)
10516 {
10517     operand *right, *left, *result;
10518     sym_link *letype ;
10519     int size, offset;
10520     char *l;
10521     symbol *tlbl, *tlbl1 ;
10522
10523     /* if signed then we do it the hard way preserve the
10524     sign bit moving it inwards */
10525     letype = getSpec(operandType(IC_LEFT(ic)));
10526     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10527
10528     if (!SPEC_USIGN(letype)) {
10529         genSignedRightShift (ic);
10530         return ;
10531     }
10532
10533     /* signed & unsigned types are treated the same : i.e. the
10534     signed is NOT propagated inwards : quoting from the
10535     ANSI - standard : "for E1 >> E2, is equivalent to division
10536     by 2**E2 if unsigned or if it has a non-negative value,
10537     otherwise the result is implementation defined ", MY definition
10538     is that the sign does not get propagated */
10539
10540     right = IC_RIGHT(ic);
10541     left  = IC_LEFT(ic);
10542     result = IC_RESULT(ic);
10543
10544     pic16_aopOp(right,ic,FALSE);
10545
10546     /* if the shift count is known then do it 
10547     as efficiently as possible */
10548     if (AOP_TYPE(right) == AOP_LIT) {
10549         genRightShiftLiteral (left,right,result,ic, 0);
10550         return ;
10551     }
10552
10553     /* shift count is unknown then we have to form 
10554     a loop get the loop count in B : Note: we take
10555     only the lower order byte since shifting
10556     more that 32 bits make no sense anyway, ( the
10557     largest size of an object can be only 32 bits ) */  
10558
10559     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10560     pic16_emitcode("inc","b");
10561     pic16_aopOp(left,ic,FALSE);
10562     pic16_aopOp(result,ic,FALSE);
10563
10564     /* now move the left to the result if they are not the
10565     same */
10566     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10567         AOP_SIZE(result) > 1) {
10568
10569         size = AOP_SIZE(result);
10570         offset=0;
10571         while (size--) {
10572             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10573             if (*l == '@' && IS_AOP_PREG(result)) {
10574
10575                 pic16_emitcode("mov","a,%s",l);
10576                 pic16_aopPut(AOP(result),"a",offset);
10577             } else
10578                 pic16_aopPut(AOP(result),l,offset);
10579             offset++;
10580         }
10581     }
10582
10583     tlbl = newiTempLabel(NULL);
10584     tlbl1= newiTempLabel(NULL);
10585     size = AOP_SIZE(result);
10586     offset = size - 1;
10587
10588     /* if it is only one byte then */
10589     if (size == 1) {
10590
10591       tlbl = newiTempLabel(NULL);
10592       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10593         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10594         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10595       }
10596
10597       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10598       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10599       pic16_emitpLabel(tlbl->key);
10600       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10601       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10602       emitSKPC;
10603       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10604
10605       goto release ;
10606     }
10607
10608     reAdjustPreg(AOP(result));
10609     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10610     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10611     CLRC;
10612     while (size--) {
10613         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10614         MOVA(l);
10615         pic16_emitcode("rrc","a");         
10616         pic16_aopPut(AOP(result),"a",offset--);
10617     }
10618     reAdjustPreg(AOP(result));
10619
10620     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10621     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10622
10623 release:
10624     pic16_freeAsmop(left,NULL,ic,TRUE);
10625     pic16_freeAsmop (right,NULL,ic,TRUE);
10626     pic16_freeAsmop(result,NULL,ic,TRUE);
10627 }
10628 #endif
10629
10630 #if (USE_GENERIC_SIGNED_SHIFT)
10631 /*-----------------------------------------------------------------*/
10632 /* genGenericShift - generates code for left or right shifting     */
10633 /*-----------------------------------------------------------------*/
10634 static void genGenericShift (iCode *ic, int isShiftLeft) {
10635   operand *left,*right, *result;
10636   int offset;
10637   int sign, signedCount;
10638   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10639   PIC_OPCODE pos_shift, neg_shift;
10640
10641   FENTRY;
10642
10643   right = IC_RIGHT(ic);
10644   left  = IC_LEFT(ic);
10645   result = IC_RESULT(ic);
10646
10647   pic16_aopOp(right,ic,FALSE);
10648   pic16_aopOp(left,ic,FALSE);
10649   pic16_aopOp(result,ic,TRUE);
10650
10651   sign = !SPEC_USIGN(operandType (left));
10652   signedCount = !SPEC_USIGN(operandType (right));
10653
10654   /* if the shift count is known then do it 
10655      as efficiently as possible */
10656   if (AOP_TYPE(right) == AOP_LIT) {
10657     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10658     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10659     // we should modify right->aopu.aop_lit here!
10660     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10661     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10662     if (isShiftLeft)
10663       pic16_genLeftShiftLiteral (left,right,result,ic);
10664     else
10665       genRightShiftLiteral (left,right,result,ic, sign);
10666
10667     goto release;
10668   } // if (right is literal)
10669
10670   /* shift count is unknown then we have to form a loop.
10671    * Note: we take only the lower order byte since shifting
10672    * more than 32 bits make no sense anyway, ( the
10673    * largest size of an object can be only 32 bits )
10674    * Note: we perform arithmetic shifts if the left operand is
10675    * signed and we do an (effective) right shift, i. e. we
10676    * shift in the sign bit from the left. */
10677    
10678   label_complete = newiTempLabel ( NULL );
10679   label_loop_pos = newiTempLabel ( NULL );
10680   label_loop_neg = NULL;
10681   label_negative = NULL;
10682   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10683   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10684
10685   if (signedCount) {
10686     // additional labels needed
10687     label_loop_neg = newiTempLabel ( NULL );
10688     label_negative = newiTempLabel ( NULL );
10689   } // if
10690
10691   // copy source to result -- this will effectively truncate the left operand to the size of result!
10692   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10693   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10694   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10695     pic16_mov2f (AOP(result),AOP(left), offset);
10696   } // for
10697
10698   // if result is longer than left, fill with zeros (or sign)
10699   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10700     if (sign && AOP_SIZE(left) > 0) {
10701       // shift signed operand -- fill with sign
10702       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10703       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10704       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10705       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10706         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10707       } // for
10708     } else {
10709       // shift unsigned operand -- fill result with zeros
10710       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10711         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10712       } // for
10713     }
10714   } // if (size mismatch)
10715
10716   pic16_mov2w (AOP(right), 0);
10717   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10718   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10719   
10720 #if 0
10721   // perform a shift by one (shift count is positive)
10722   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10723   // 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])
10724   pic16_emitpLabel (label_loop_pos->key);
10725   emitCLRC;
10726   if (sign && (pos_shift == POC_RRCF)) {
10727     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10728     emitSETC;
10729   } // if
10730   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10731   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10732   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10733 #else
10734   // perform a shift by one (shift count is positive)
10735   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10736   // 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])
10737   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10738   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10739   emitCLRC;
10740   pic16_emitpLabel (label_loop_pos->key);
10741   if (sign && (pos_shift == POC_RRCF)) {
10742     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10743     emitSETC;
10744   } // if
10745   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10746   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10747   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10748   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10749 #endif
10750
10751   if (signedCount) {
10752     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10753
10754     pic16_emitpLabel (label_negative->key);
10755     // perform a shift by -1 (shift count is negative)
10756     // 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)
10757     emitCLRC;
10758     pic16_emitpLabel (label_loop_neg->key);
10759     if (sign && (neg_shift == POC_RRCF)) {
10760       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10761       emitSETC;
10762     } // if
10763     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10764     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10765     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10766     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10767   } // if (signedCount)
10768
10769   pic16_emitpLabel (label_complete->key);
10770
10771 release:
10772   pic16_freeAsmop (right,NULL,ic,TRUE);
10773   pic16_freeAsmop(left,NULL,ic,TRUE);
10774   pic16_freeAsmop(result,NULL,ic,TRUE);
10775 }
10776
10777 static void genLeftShift (iCode *ic) {
10778   genGenericShift (ic, 1);
10779 }
10780
10781 static void genRightShift (iCode *ic) {
10782   genGenericShift (ic, 0);
10783 }
10784 #endif
10785
10786
10787 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10788 void pic16_loadFSR0(operand *op, int lit)
10789 {
10790   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10791     if (AOP_TYPE(op) == AOP_LIT) {
10792       /* handle 12 bit integers correctly */
10793       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10794       if ((val & 0x0fff) != val) {
10795         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10796                 val, (val & 0x0fff) );
10797         val &= 0x0fff;
10798       }
10799       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10800     } else {
10801       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10802     }
10803   } else {
10804     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10805     // set up FSR0 with address of result
10806     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10807     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10808   }
10809 }
10810
10811 /*----------------------------------------------------------------*/
10812 /* pic16_derefPtr - move one byte from the location ptr points to */
10813 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10814 /*                  to the location ptr points to (doWrite != 0)   */
10815 /*----------------------------------------------------------------*/
10816 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10817 {
10818   if (!IS_PTR(operandType(ptr)))
10819   {
10820     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10821     else pic16_mov2w (AOP(ptr), 0);
10822     return;
10823   }
10824
10825   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10826   /* We might determine pointer type right here: */
10827   p_type = DCL_TYPE(operandType(ptr));
10828
10829   switch (p_type) {
10830     case FPOINTER:
10831     case POINTER:
10832       if (!fsr0_setup || !*fsr0_setup)
10833       {
10834         pic16_loadFSR0( ptr, 0 );
10835         if (fsr0_setup) *fsr0_setup = 1;
10836       }
10837       if (doWrite)
10838         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10839       else
10840         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10841       break;
10842
10843     case GPOINTER:
10844       if (AOP(ptr)->aopu.aop_reg[2]) {
10845         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10846         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10847         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10848         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10849         pic16_mov2w(AOP(ptr), 2);
10850         pic16_callGenericPointerRW(doWrite, 1);
10851       } else {
10852         // data pointer (just 2 byte given)
10853         if (!fsr0_setup || !*fsr0_setup)
10854         {
10855           pic16_loadFSR0( ptr, 0 );
10856           if (fsr0_setup) *fsr0_setup = 1;
10857         }
10858         if (doWrite)
10859           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10860         else
10861           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10862       }
10863       break;
10864
10865     default:
10866       assert (0 && "invalid pointer type specified");
10867       break;
10868   }
10869 }
10870
10871 /*-----------------------------------------------------------------*/
10872 /* genUnpackBits - generates code for unpacking bits               */
10873 /*-----------------------------------------------------------------*/
10874 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10875 {    
10876   int shCnt ;
10877   sym_link *etype, *letype;
10878   int blen=0, bstr=0;
10879   int lbstr;
10880   int same;
10881   pCodeOp *op;
10882
10883   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10884   etype = getSpec(operandType(result));
10885   letype = getSpec(operandType(left));
10886
10887   //    if(IS_BITFIELD(etype)) {
10888   blen = SPEC_BLEN(etype);
10889   bstr = SPEC_BSTR(etype);
10890   //    }
10891
10892   lbstr = SPEC_BSTR( letype );
10893
10894   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10895       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10896
10897 #if 1
10898   if((blen == 1) && (bstr < 8)
10899       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10900     /* it is a single bit, so use the appropriate bit instructions */
10901     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10902
10903     same = pic16_sameRegs(AOP(left),AOP(result));
10904     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10905     pic16_emitpcode(POC_CLRF, op);
10906
10907     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10908       /* workaround to reduce the extra lfsr instruction */
10909       pic16_emitpcode(POC_BTFSC,
10910           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10911     } else {
10912       assert (PIC_IS_DATA_PTR (operandType(left)));
10913       pic16_loadFSR0 (left, 0);
10914       pic16_emitpcode(POC_BTFSC,
10915           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10916     }
10917
10918     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10919       /* unsigned bitfields result in either 0 or 1 */
10920       pic16_emitpcode(POC_INCF, op);
10921     } else {
10922       /* signed bitfields result in either 0 or -1 */
10923       pic16_emitpcode(POC_DECF, op);
10924     }
10925     if (same) {
10926       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10927     }
10928
10929     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10930     return;
10931   }
10932
10933 #endif
10934
10935   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10936     // access symbol directly
10937     pic16_mov2w (AOP(left), 0);
10938   } else {
10939     pic16_derefPtr (left, ptype, 0, NULL);
10940   }
10941
10942   /* if we have bitdisplacement then it fits   */
10943   /* into this byte completely or if length is */
10944   /* less than a byte                          */
10945   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10946
10947     /* shift right acc */
10948     AccRsh(shCnt, 0);
10949
10950     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10951           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10952
10953     /* VR -- normally I would use the following, but since we use the hack,
10954      * to avoid the masking from AccRsh, why not mask it right now? */
10955
10956     /*
10957        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10958      */
10959
10960     /* extend signed bitfields to 8 bits */
10961     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10962     {
10963       assert (blen + bstr > 0);
10964       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10965       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10966     }
10967
10968     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10969
10970     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10971     return ;
10972   }
10973
10974   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10975   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10976   exit(EXIT_FAILURE);
10977
10978   return ;
10979 }
10980
10981
10982 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10983 {
10984   int size, offset = 0, leoffset=0 ;
10985
10986         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10987         pic16_aopOp(result, ic, TRUE);
10988
10989         FENTRY;
10990
10991         size = AOP_SIZE(result);
10992 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10993
10994
10995 #if 1
10996         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10997                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10998                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10999                 goto release;
11000         }
11001 #endif
11002
11003         if(AOP(left)->aopu.pcop->type == PO_DIR)
11004                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11005
11006         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11007
11008         while (size--) {
11009                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11010                 
11011 //              pic16_DumpOp("(result)",result);
11012                 if(is_LitAOp(AOP(result))) {
11013                         pic16_mov2w(AOP(left), offset); // patch 8
11014                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11015                 } else {
11016                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11017                                 pic16_popGet(AOP(left), offset), //patch 8
11018                                 pic16_popGet(AOP(result), offset)));
11019                 }
11020
11021                 offset++;
11022                 leoffset++;
11023         }
11024
11025 release:
11026     pic16_freeAsmop(result,NULL,ic,TRUE);
11027 }
11028
11029
11030
11031 /*-----------------------------------------------------------------*/
11032 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11033 /*-----------------------------------------------------------------*/
11034 static void genNearPointerGet (operand *left, 
11035                                operand *result, 
11036                                iCode *ic)
11037 {
11038 //  asmop *aop = NULL;
11039   //regs *preg = NULL ;
11040   sym_link *rtype, *retype;
11041   sym_link *ltype, *letype;
11042
11043     FENTRY;
11044     
11045     rtype = operandType(result);
11046     retype= getSpec(rtype);
11047     ltype = operandType(left);
11048     letype= getSpec(ltype);
11049     
11050     pic16_aopOp(left,ic,FALSE);
11051
11052 //    pic16_DumpOp("(left)",left);
11053 //    pic16_DumpOp("(result)",result);
11054
11055     /* if left is rematerialisable and
11056      * result is not bit variable type and
11057      * the left is pointer to data space i.e
11058      * lower 128 bytes of space */
11059     
11060     if (AOP_TYPE(left) == AOP_PCODE
11061       && !IS_BITFIELD(retype)
11062       && DCL_TYPE(ltype) == POINTER) {
11063
11064         genDataPointerGet (left,result,ic);
11065         pic16_freeAsmop(left, NULL, ic, TRUE);
11066         return ;
11067     }
11068     
11069     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11070     pic16_aopOp (result,ic,TRUE);
11071     
11072     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11073
11074 #if 1
11075     if(IS_BITFIELD( retype )
11076       && (SPEC_BLEN(operandType(result))==1)
11077     ) {
11078       iCode *nextic;
11079       pCodeOp *jop;
11080       int bitstrt, bytestrt;
11081
11082         /* if this is bitfield of size 1, see if we are checking the value
11083          * of a single bit in an if-statement,
11084          * if yes, then don't generate usual code, but execute the
11085          * genIfx directly -- VR */
11086
11087         nextic = ic->next;
11088
11089         /* CHECK: if next iCode is IFX
11090          * and current result operand is nextic's conditional operand
11091          * and current result operand live ranges ends at nextic's key number
11092          */
11093         if((nextic->op == IFX)
11094           && (result == IC_COND(nextic))
11095           && (OP_LIVETO(result) == nextic->seq)
11096           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11097           ) {
11098             /* everything is ok then */
11099             /* find a way to optimize the genIfx iCode */
11100
11101             bytestrt = SPEC_BSTR(operandType(result))/8;
11102             bitstrt = SPEC_BSTR(operandType(result))%8;
11103             
11104             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11105
11106             genIfxpCOpJump(nextic, jop);
11107             
11108             pic16_freeAsmop(left, NULL, ic, TRUE);
11109             pic16_freeAsmop(result, NULL, ic, TRUE);
11110             return;
11111         }
11112     }
11113 #endif
11114
11115     /* if bitfield then unpack the bits */
11116     if (IS_BITFIELD(letype)) 
11117       genUnpackBits (result, left, NULL, POINTER);
11118     else {
11119       /* we have can just get the values */
11120       int size = AOP_SIZE(result);
11121       int offset = 0;   
11122         
11123       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11124
11125       pic16_loadFSR0( left, 0 );
11126
11127       while(size--) {
11128         if(size) {
11129           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11130                 pic16_popGet(AOP(result), offset++)));
11131         } else {
11132           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11133                 pic16_popGet(AOP(result), offset++)));
11134         }
11135       }
11136     }
11137
11138 #if 0
11139     /* now some housekeeping stuff */
11140     if (aop) {
11141       /* we had to allocate for this iCode */
11142       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11143       pic16_freeAsmop(NULL,aop,ic,TRUE);
11144     } else { 
11145       /* we did not allocate which means left
11146        * already in a pointer register, then
11147        * if size > 0 && this could be used again
11148        * we have to point it back to where it 
11149        * belongs */
11150       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11151       if (AOP_SIZE(result) > 1
11152         && !OP_SYMBOL(left)->remat
11153         && ( OP_SYMBOL(left)->liveTo > ic->seq
11154             || ic->depth )) {
11155 //        int size = AOP_SIZE(result) - 1;
11156 //        while (size--)
11157 //          pic16_emitcode("dec","%s",rname);
11158         }
11159     }
11160 #endif
11161
11162     /* done */
11163     pic16_freeAsmop(left,NULL,ic,TRUE);
11164     pic16_freeAsmop(result,NULL,ic,TRUE);
11165 }
11166
11167 /*-----------------------------------------------------------------*/
11168 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11169 /*-----------------------------------------------------------------*/
11170 static void genPagedPointerGet (operand *left, 
11171                                operand *result, 
11172                                iCode *ic)
11173 {
11174     asmop *aop = NULL;
11175     regs *preg = NULL ;
11176     char *rname ;
11177     sym_link *rtype, *retype;    
11178
11179     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11180
11181     rtype = operandType(result);
11182     retype= getSpec(rtype);
11183     
11184     pic16_aopOp(left,ic,FALSE);
11185
11186   /* if the value is already in a pointer register
11187        then don't need anything more */
11188     if (!AOP_INPREG(AOP(left))) {
11189         /* otherwise get a free pointer register */
11190         aop = newAsmop(0);
11191         preg = getFreePtr(ic,&aop,FALSE);
11192         pic16_emitcode("mov","%s,%s",
11193                 preg->name,
11194                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11195         rname = preg->name ;
11196     } else
11197         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11198     
11199     pic16_freeAsmop(left,NULL,ic,TRUE);
11200     pic16_aopOp (result,ic,TRUE);
11201
11202     /* if bitfield then unpack the bits */
11203     if (IS_BITFIELD(retype)) 
11204         genUnpackBits (result,left,rname,PPOINTER);
11205     else {
11206         /* we have can just get the values */
11207         int size = AOP_SIZE(result);
11208         int offset = 0 ;        
11209         
11210         while (size--) {
11211             
11212             pic16_emitcode("movx","a,@%s",rname);
11213             pic16_aopPut(AOP(result),"a",offset);
11214             
11215             offset++ ;
11216             
11217             if (size)
11218                 pic16_emitcode("inc","%s",rname);
11219         }
11220     }
11221
11222     /* now some housekeeping stuff */
11223     if (aop) {
11224         /* we had to allocate for this iCode */
11225         pic16_freeAsmop(NULL,aop,ic,TRUE);
11226     } else { 
11227         /* we did not allocate which means left
11228            already in a pointer register, then
11229            if size > 0 && this could be used again
11230            we have to point it back to where it 
11231            belongs */
11232         if (AOP_SIZE(result) > 1 &&
11233             !OP_SYMBOL(left)->remat &&
11234             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11235               ic->depth )) {
11236             int size = AOP_SIZE(result) - 1;
11237             while (size--)
11238                 pic16_emitcode("dec","%s",rname);
11239         }
11240     }
11241
11242     /* done */
11243     pic16_freeAsmop(result,NULL,ic,TRUE);
11244     
11245         
11246 }
11247
11248 #if 0
11249 /* This code is not adjusted to PIC16 and fails utterly.
11250  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11251
11252 /*-----------------------------------------------------------------*/
11253 /* genFarPointerGet - gget value from far space                    */
11254 /*-----------------------------------------------------------------*/
11255 static void genFarPointerGet (operand *left,
11256                               operand *result, iCode *ic)
11257 {
11258     int size, offset ;
11259     sym_link *retype = getSpec(operandType(result));
11260
11261     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11262
11263     pic16_aopOp(left,ic,FALSE);
11264
11265     /* if the operand is already in dptr 
11266     then we do nothing else we move the value to dptr */
11267     if (AOP_TYPE(left) != AOP_STR) {
11268         /* if this is remateriazable */
11269         if (AOP_TYPE(left) == AOP_IMMD)
11270             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11271         else { /* we need to get it byte by byte */
11272             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11273             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11274             if (options.model == MODEL_FLAT24)
11275             {
11276                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11277             }
11278         }
11279     }
11280     /* so dptr know contains the address */
11281     pic16_freeAsmop(left,NULL,ic,TRUE);
11282     pic16_aopOp(result,ic,TRUE);
11283
11284     /* if bit then unpack */
11285     if (IS_BITFIELD(retype)) 
11286         genUnpackBits(result,left,"dptr",FPOINTER);
11287     else {
11288         size = AOP_SIZE(result);
11289         offset = 0 ;
11290
11291         while (size--) {
11292             pic16_emitcode("movx","a,@dptr");
11293             pic16_aopPut(AOP(result),"a",offset++);
11294             if (size)
11295                 pic16_emitcode("inc","dptr");
11296         }
11297     }
11298
11299     pic16_freeAsmop(result,NULL,ic,TRUE);
11300 }
11301 #endif
11302
11303 #if 0
11304 /*-----------------------------------------------------------------*/
11305 /* genCodePointerGet - get value from code space                  */
11306 /*-----------------------------------------------------------------*/
11307 static void genCodePointerGet (operand *left,
11308                                 operand *result, iCode *ic)
11309 {
11310     int size, offset ;
11311     sym_link *retype = getSpec(operandType(result));
11312
11313     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11314
11315     pic16_aopOp(left,ic,FALSE);
11316
11317     /* if the operand is already in dptr 
11318     then we do nothing else we move the value to dptr */
11319     if (AOP_TYPE(left) != AOP_STR) {
11320         /* if this is remateriazable */
11321         if (AOP_TYPE(left) == AOP_IMMD)
11322             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11323         else { /* we need to get it byte by byte */
11324             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11325             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11326             if (options.model == MODEL_FLAT24)
11327             {
11328                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11329             }
11330         }
11331     }
11332     /* so dptr know contains the address */
11333     pic16_freeAsmop(left,NULL,ic,TRUE);
11334     pic16_aopOp(result,ic,FALSE);
11335
11336     /* if bit then unpack */
11337     if (IS_BITFIELD(retype)) 
11338         genUnpackBits(result,left,"dptr",CPOINTER);
11339     else {
11340         size = AOP_SIZE(result);
11341         offset = 0 ;
11342
11343         while (size--) {
11344             pic16_emitcode("clr","a");
11345             pic16_emitcode("movc","a,@a+dptr");
11346             pic16_aopPut(AOP(result),"a",offset++);
11347             if (size)
11348                 pic16_emitcode("inc","dptr");
11349         }
11350     }
11351
11352     pic16_freeAsmop(result,NULL,ic,TRUE);
11353 }
11354 #endif
11355
11356 #if 0
11357 /*-----------------------------------------------------------------*/
11358 /* genGenPointerGet - gget value from generic pointer space        */
11359 /*-----------------------------------------------------------------*/
11360 static void genGenPointerGet (operand *left,
11361                               operand *result, iCode *ic)
11362 {
11363   int size, offset, lit;
11364   sym_link *retype = getSpec(operandType(result));
11365
11366         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11367         pic16_aopOp(left,ic,FALSE);
11368         pic16_aopOp(result,ic,FALSE);
11369         size = AOP_SIZE(result);
11370
11371         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11372
11373         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11374
11375                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11376                 // load FSR0 from immediate
11377                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11378
11379 //              pic16_loadFSR0( left );
11380
11381                 offset = 0;
11382                 while(size--) {
11383                         if(size) {
11384                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11385                         } else {
11386                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11387                         }
11388                         offset++;
11389                 }
11390                 goto release;
11391
11392         }
11393         else { /* we need to get it byte by byte */
11394                 // set up FSR0 with address from left
11395                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11396                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11397                 
11398                 offset = 0 ;
11399
11400                 while(size--) {
11401                         if(size) {
11402                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11403                         } else {
11404                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11405                         }
11406                         offset++;
11407                 }
11408                 goto release;
11409         }
11410
11411   /* if bit then unpack */
11412         if (IS_BITFIELD(retype)) 
11413                 genUnpackBits(result,left,"BAD",GPOINTER);
11414
11415         release:
11416         pic16_freeAsmop(left,NULL,ic,TRUE);
11417         pic16_freeAsmop(result,NULL,ic,TRUE);
11418
11419 }
11420 #endif
11421
11422
11423 /*-----------------------------------------------------------------*/
11424 /* genGenPointerGet - gget value from generic pointer space        */
11425 /*-----------------------------------------------------------------*/
11426 static void genGenPointerGet (operand *left,
11427                               operand *result, iCode *ic)
11428 {
11429   int size, offset, lit;
11430   sym_link *letype = getSpec(operandType(left));
11431
11432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11433     pic16_aopOp(left,ic,FALSE);
11434     pic16_aopOp(result,ic,TRUE);
11435     size = AOP_SIZE(result);
11436
11437     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11438   
11439     /* if bit then unpack */
11440     if (IS_BITFIELD(letype)) {
11441       genUnpackBits(result,left,"BAD",GPOINTER);
11442       goto release;
11443     }
11444
11445     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11446
11447       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11448       // load FSR0 from immediate
11449       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11450
11451       werror(W_POSSBUG2, __FILE__, __LINE__);
11452
11453       offset = 0;
11454       while(size--) {
11455         if(size) {
11456           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11457         } else {
11458           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11459         }
11460         offset++;
11461       }
11462
11463       goto release;
11464
11465     } else { /* we need to get it byte by byte */
11466
11467       /* set up WREG:PRODL:FSR0L with address from left */
11468       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11469       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11470       pic16_mov2w(AOP(left), 2);
11471       pic16_callGenericPointerRW(0, size);
11472       
11473       assignResultValue(result, size, 1);
11474       
11475       goto release;
11476     }
11477
11478 release:
11479   pic16_freeAsmop(left,NULL,ic,TRUE);
11480   pic16_freeAsmop(result,NULL,ic,TRUE);
11481 }
11482
11483 /*-----------------------------------------------------------------*/
11484 /* genConstPointerGet - get value from const generic pointer space */
11485 /*-----------------------------------------------------------------*/
11486 static void genConstPointerGet (operand *left,
11487                                 operand *result, iCode *ic)
11488 {
11489   //sym_link *retype = getSpec(operandType(result));
11490   // symbol *albl = newiTempLabel(NULL);        // patch 15
11491   // symbol *blbl = newiTempLabel(NULL);        //
11492   // PIC_OPCODE poc;                            // patch 15
11493   int size;
11494   int offset = 0;
11495
11496   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11497   pic16_aopOp(left,ic,FALSE);
11498   pic16_aopOp(result,ic,TRUE);
11499   size = AOP_SIZE(result);
11500
11501   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11502
11503   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11504
11505   // set up table pointer
11506   if( (AOP_TYPE(left) == AOP_PCODE) 
11507       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11508           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11509     {
11510       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11511       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11512       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11513       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11514       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11515       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11516   } else {
11517     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11518     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11519     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11520   }
11521
11522   while(size--) {
11523     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11524     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11525     offset++;
11526   }
11527     
11528   pic16_freeAsmop(left,NULL,ic,TRUE);
11529   pic16_freeAsmop(result,NULL,ic,TRUE);
11530 }
11531
11532
11533 /*-----------------------------------------------------------------*/
11534 /* genPointerGet - generate code for pointer get                   */
11535 /*-----------------------------------------------------------------*/
11536 static void genPointerGet (iCode *ic)
11537 {
11538   operand *left, *result ;
11539   sym_link *type, *etype;
11540   int p_type;
11541
11542     FENTRY;
11543     
11544     left = IC_LEFT(ic);
11545     result = IC_RESULT(ic) ;
11546
11547     /* depending on the type of pointer we need to
11548     move it to the correct pointer register */
11549     type = operandType(left);
11550     etype = getSpec(type);
11551
11552 #if 0
11553     if (IS_PTR_CONST(type))
11554 #else
11555     if (IS_CODEPTR(type))
11556 #endif
11557       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11558
11559     /* if left is of type of pointer then it is simple */
11560     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11561       p_type = DCL_TYPE(type);
11562     else {
11563       /* we have to go by the storage class */
11564       p_type = PTR_TYPE(SPEC_OCLS(etype));
11565
11566       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11567
11568       if (SPEC_OCLS(etype)->codesp ) {
11569         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11570         //p_type = CPOINTER ;   
11571       } else
11572       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11573         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11574         /*p_type = FPOINTER ;*/ 
11575       } else
11576       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11577         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11578         /* p_type = PPOINTER; */
11579       } else
11580       if (SPEC_OCLS(etype) == idata ) {
11581         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11582         /* p_type = IPOINTER; */
11583       } else {
11584         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11585         /* p_type = POINTER ; */
11586       }
11587     }
11588
11589     /* now that we have the pointer type we assign
11590     the pointer values */
11591     switch (p_type) {
11592       case POINTER:     
11593       case FPOINTER:
11594       case IPOINTER:
11595         genNearPointerGet (left,result,ic);
11596         break;
11597
11598       case PPOINTER:
11599         genPagedPointerGet(left,result,ic);
11600         break;
11601
11602 #if 0
11603       /* PICs do not support FAR pointers... */
11604       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11605       case FPOINTER:
11606         genFarPointerGet (left,result,ic);
11607         break;
11608 #endif
11609
11610       case CPOINTER:
11611         genConstPointerGet (left,result,ic);
11612         //pic16_emitcodePointerGet (left,result,ic);
11613         break;
11614
11615       case GPOINTER:
11616 #if 0
11617       if (IS_PTR_CONST(type))
11618         genConstPointerGet (left,result,ic);
11619       else
11620 #endif
11621         genGenPointerGet (left,result,ic);
11622       break;
11623
11624     default:
11625       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11626               "genPointerGet: illegal pointer type");
11627     
11628     }
11629 }
11630
11631 /*-----------------------------------------------------------------*/
11632 /* genPackBits - generates code for packed bit storage             */
11633 /*-----------------------------------------------------------------*/
11634 static void genPackBits (sym_link    *etype , operand *result,
11635                          operand *right ,
11636                          char *rname, int p_type)
11637 {
11638   int shCnt = 0 ;
11639   int offset = 0  ;
11640   int rLen = 0 ;
11641   int blen, bstr ;   
11642   int shifted_and_masked = 0;
11643   unsigned long lit = (unsigned long)-1;
11644   sym_link *retype;
11645
11646   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11647   blen = SPEC_BLEN(etype);
11648   bstr = SPEC_BSTR(etype);
11649
11650   retype = getSpec(operandType(right));
11651
11652   if(AOP_TYPE(right) == AOP_LIT) {
11653     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11654     
11655     if((blen == 1) && (bstr < 8)) {
11656       /* it is a single bit, so use the appropriate bit instructions */
11657
11658       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11659
11660       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11661         /* workaround to reduce the extra lfsr instruction */
11662         if(lit) {
11663           pic16_emitpcode(POC_BSF,
11664               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11665         } else {
11666           pic16_emitpcode(POC_BCF,
11667               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11668         }
11669       } else {
11670         if (PIC_IS_DATA_PTR(operandType(result))) {
11671           pic16_loadFSR0(result, 0);
11672           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11673               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11674         } else {
11675           /* get old value */
11676           pic16_derefPtr (result, p_type, 0, NULL);
11677           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11678               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11679           /* write back new value */
11680           pic16_derefPtr (result, p_type, 1, NULL);
11681         }
11682       }
11683
11684       return;
11685     }
11686     /* IORLW below is more efficient */
11687     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11688     lit = (lit & ((1UL << blen) - 1)) << bstr;
11689     shifted_and_masked = 1;
11690     offset++;
11691   } else
11692     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11693         && IS_BITFIELD(retype) 
11694         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11695         && (blen == 1)) {
11696       int rblen, rbstr;
11697
11698       rblen = SPEC_BLEN( retype );
11699       rbstr = SPEC_BSTR( retype );
11700
11701       if(IS_BITFIELD(etype)) {
11702         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11703         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11704       } else {
11705         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11706       }
11707
11708       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11709
11710       if(IS_BITFIELD(etype)) {
11711         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11712       } else {
11713         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11714       }
11715
11716       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11717
11718       return;
11719     } else {
11720       /* move right to W */
11721       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11722     }
11723
11724   /* if the bit length is less than or   */
11725   /* it exactly fits a byte then         */
11726   if((shCnt=SPEC_BSTR(etype))
11727       || SPEC_BLEN(etype) <= 8 )  {
11728     int fsr0_setup = 0;
11729
11730     if (blen != 8 || (bstr % 8) != 0) {
11731       // we need to combine the value with the old value
11732       if(!shifted_and_masked)
11733       {
11734         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11735
11736         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11737             SPEC_BSTR(etype), SPEC_BLEN(etype));
11738
11739         /* shift left acc, do NOT mask the result again */
11740         AccLsh(shCnt, 0);
11741
11742         /* using PRODH as a temporary register here */
11743         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11744       }
11745
11746       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11747         || IS_DIRECT(result)) {
11748         /* access symbol directly */
11749         pic16_mov2w (AOP(result), 0);
11750       } else {
11751         /* get old value */
11752         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11753       }
11754 #if 1
11755       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11756             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11757                             (unsigned char)(0xff >> (8-bstr))) ));
11758       if (!shifted_and_masked) {
11759         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11760       } else {
11761         /* We have the shifted and masked (literal) right value in `lit' */
11762         if (lit != 0)
11763           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11764       }
11765     } else { // if (blen == 8 && (bstr % 8) == 0)
11766         if (shifted_and_masked) {
11767             // move right (literal) to WREG (only case where right is not yet in WREG)
11768             pic16_mov2w(AOP(right), (bstr / 8));
11769         }
11770     }
11771
11772     /* write new value back */
11773     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11774         || IS_DIRECT(result)) {
11775       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11776     } else {
11777       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11778     }
11779 #endif
11780
11781     return;
11782   }
11783
11784
11785 #if 0
11786   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11787   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11788   exit(EXIT_FAILURE);
11789 #endif
11790
11791
11792   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11793   rLen = SPEC_BLEN(etype)-8;
11794
11795   /* now generate for lengths greater than one byte */
11796   while (1) {
11797     rLen -= 8 ;
11798     if (rLen <= 0 ) {
11799       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11800       break ;
11801     }
11802
11803     switch (p_type) {
11804       case POINTER:
11805         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11806         break;
11807
11808         /*
11809            case FPOINTER:
11810            MOVA(l);
11811            pic16_emitcode("movx","@dptr,a");
11812            break;
11813
11814            case GPOINTER:
11815            MOVA(l);
11816            DEBUGpic16_emitcode(";lcall","__gptrput");
11817            break;  
11818          */
11819       default:
11820         assert(0);
11821     }   
11822
11823
11824     pic16_mov2w(AOP(right), offset++);
11825   }
11826
11827   /* last last was not complete */
11828   if (rLen)   {
11829     /* save the byte & read byte */
11830     switch (p_type) {
11831       case POINTER:
11832         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11833         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11834         break;
11835
11836         /*
11837            case FPOINTER:
11838            pic16_emitcode ("mov","b,a");
11839            pic16_emitcode("movx","a,@dptr");
11840            break;
11841
11842            case GPOINTER:
11843            pic16_emitcode ("push","b");
11844            pic16_emitcode ("push","acc");
11845            pic16_emitcode ("lcall","__gptrget");
11846            pic16_emitcode ("pop","b");
11847            break;
11848          */
11849       default:
11850         assert(0);
11851     }
11852     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11853     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11854     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11855     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11856     //        pic16_emitcode ("orl","a,b");
11857   }
11858
11859   //    if (p_type == GPOINTER)
11860   //        pic16_emitcode("pop","b");
11861
11862   switch (p_type) {
11863
11864     case POINTER:
11865       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11866       //        pic16_emitcode("mov","@%s,a",rname);
11867       break;
11868       /*
11869          case FPOINTER:
11870          pic16_emitcode("movx","@dptr,a");
11871          break;
11872
11873          case GPOINTER:
11874          DEBUGpic16_emitcode(";lcall","__gptrput");
11875          break;                 
11876        */
11877     default:
11878       assert(0);
11879   }
11880
11881   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11882 }
11883
11884 /*-----------------------------------------------------------------*/
11885 /* genDataPointerSet - remat pointer to data space                 */
11886 /*-----------------------------------------------------------------*/
11887 static void genDataPointerSet(operand *right,
11888                               operand *result,
11889                               iCode *ic)
11890 {
11891   int size, offset = 0, resoffset=0 ;
11892
11893     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11894     pic16_aopOp(right,ic,FALSE);
11895
11896     size = AOP_SIZE(right);
11897
11898 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11899
11900 #if 0
11901     if ( AOP_TYPE(result) == AOP_PCODE) {
11902       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11903               AOP(result)->aopu.pcop->name,
11904                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11905               PCOR(AOP(result)->aopu.pcop)->instance:
11906               PCOI(AOP(result)->aopu.pcop)->offset);
11907     }
11908 #endif
11909
11910     if(AOP(result)->aopu.pcop->type == PO_DIR)
11911       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11912
11913     while (size--) {
11914       if (AOP_TYPE(right) == AOP_LIT) {
11915         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11916         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11917       } else {
11918         pic16_mov2w(AOP(right), offset);
11919         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11920       }
11921       offset++;
11922       resoffset++;
11923     }
11924
11925     pic16_freeAsmop(right,NULL,ic,TRUE);
11926 }
11927
11928
11929
11930 /*-----------------------------------------------------------------*/
11931 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11932 /*-----------------------------------------------------------------*/
11933 static void genNearPointerSet (operand *right,
11934                                operand *result, 
11935                                iCode *ic)
11936 {
11937   asmop *aop = NULL;
11938   sym_link *retype;
11939   sym_link *ptype = operandType(result);
11940   sym_link *resetype;
11941     
11942     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11943     retype= getSpec(operandType(right));
11944     resetype = getSpec(operandType(result));
11945   
11946     pic16_aopOp(result,ic,FALSE);
11947     
11948     /* if the result is rematerializable &
11949      * in data space & not a bit variable */
11950         
11951     /* and result is not a bit variable */
11952     if (AOP_TYPE(result) == AOP_PCODE
11953 //      && AOP_TYPE(result) == AOP_IMMD
11954       && DCL_TYPE(ptype) == POINTER
11955       && !IS_BITFIELD(retype)
11956       && !IS_BITFIELD(resetype)) {
11957
11958         genDataPointerSet (right,result,ic);
11959         pic16_freeAsmop(result,NULL,ic,TRUE);
11960       return;
11961     }
11962
11963     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11964     pic16_aopOp(right,ic,FALSE);
11965     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11966
11967     /* if bitfield then unpack the bits */
11968     if (IS_BITFIELD(resetype)) {
11969       genPackBits (resetype, result, right, NULL, POINTER);
11970     } else {
11971       /* we have can just get the values */
11972       int size = AOP_SIZE(right);
11973       int offset = 0 ;    
11974
11975         pic16_loadFSR0(result, 0);
11976             
11977         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11978         while (size--) {
11979           if (AOP_TYPE(right) == AOP_LIT) {
11980             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11981             if (size) {
11982               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11983             } else {
11984               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11985             }
11986           } else { // no literal
11987             if(size) {
11988               pic16_emitpcode(POC_MOVFF,
11989                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11990                   pic16_popCopyReg(&pic16_pc_postinc0)));
11991             } else {
11992               pic16_emitpcode(POC_MOVFF,
11993                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11994                   pic16_popCopyReg(&pic16_pc_indf0)));
11995             }
11996           }
11997           
11998           offset++;
11999         }
12000     }
12001
12002     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12003     /* now some housekeeping stuff */
12004     if (aop) {
12005       /* we had to allocate for this iCode */
12006       pic16_freeAsmop(NULL,aop,ic,TRUE);
12007     } else { 
12008       /* we did not allocate which means left
12009        * already in a pointer register, then
12010        * if size > 0 && this could be used again
12011        * we have to point it back to where it 
12012        * belongs */
12013       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12014       if (AOP_SIZE(right) > 1
12015         && !OP_SYMBOL(result)->remat
12016         && ( OP_SYMBOL(result)->liveTo > ic->seq
12017         || ic->depth )) {
12018
12019           int size = AOP_SIZE(right) - 1;
12020
12021             while (size--)
12022               pic16_emitcode("decf","fsr0,f");
12023               //pic16_emitcode("dec","%s",rname);
12024       }
12025     }
12026
12027     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12028     /* done */
12029 //release:
12030     pic16_freeAsmop(right,NULL,ic,TRUE);
12031     pic16_freeAsmop(result,NULL,ic,TRUE);
12032 }
12033
12034 /*-----------------------------------------------------------------*/
12035 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12036 /*-----------------------------------------------------------------*/
12037 static void genPagedPointerSet (operand *right,
12038                                operand *result, 
12039                                iCode *ic)
12040 {
12041     asmop *aop = NULL;
12042     regs *preg = NULL ;
12043     char *rname , *l;
12044     sym_link *retype;
12045        
12046     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12047
12048     retype= getSpec(operandType(right));
12049     
12050     pic16_aopOp(result,ic,FALSE);
12051     
12052     /* if the value is already in a pointer register
12053        then don't need anything more */
12054     if (!AOP_INPREG(AOP(result))) {
12055         /* otherwise get a free pointer register */
12056         aop = newAsmop(0);
12057         preg = getFreePtr(ic,&aop,FALSE);
12058         pic16_emitcode("mov","%s,%s",
12059                 preg->name,
12060                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12061         rname = preg->name ;
12062     } else
12063         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12064     
12065     pic16_freeAsmop(result,NULL,ic,TRUE);
12066     pic16_aopOp (right,ic,FALSE);
12067
12068     /* if bitfield then unpack the bits */
12069     if (IS_BITFIELD(retype)) 
12070         genPackBits (retype,result,right,rname,PPOINTER);
12071     else {
12072         /* we have can just get the values */
12073         int size = AOP_SIZE(right);
12074         int offset = 0 ;        
12075         
12076         while (size--) {
12077             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12078             
12079             MOVA(l);
12080             pic16_emitcode("movx","@%s,a",rname);
12081
12082             if (size)
12083                 pic16_emitcode("inc","%s",rname);
12084
12085             offset++;
12086         }
12087     }
12088     
12089     /* now some housekeeping stuff */
12090     if (aop) {
12091         /* we had to allocate for this iCode */
12092         pic16_freeAsmop(NULL,aop,ic,TRUE);
12093     } else { 
12094         /* we did not allocate which means left
12095            already in a pointer register, then
12096            if size > 0 && this could be used again
12097            we have to point it back to where it 
12098            belongs */
12099         if (AOP_SIZE(right) > 1 &&
12100             !OP_SYMBOL(result)->remat &&
12101             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12102               ic->depth )) {
12103             int size = AOP_SIZE(right) - 1;
12104             while (size--)
12105                 pic16_emitcode("dec","%s",rname);
12106         }
12107     }
12108
12109     /* done */
12110     pic16_freeAsmop(right,NULL,ic,TRUE);
12111     
12112         
12113 }
12114
12115 #if 0
12116 /* This code is not adjusted to PIC16 and fails utterly...
12117  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12118
12119 /*-----------------------------------------------------------------*/
12120 /* genFarPointerSet - set value from far space                     */
12121 /*-----------------------------------------------------------------*/
12122 static void genFarPointerSet (operand *right,
12123                               operand *result, iCode *ic)
12124 {
12125     int size, offset ;
12126     sym_link *retype = getSpec(operandType(right));
12127
12128     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12129     pic16_aopOp(result,ic,FALSE);
12130
12131     /* if the operand is already in dptr 
12132     then we do nothing else we move the value to dptr */
12133     if (AOP_TYPE(result) != AOP_STR) {
12134         /* if this is remateriazable */
12135         if (AOP_TYPE(result) == AOP_IMMD)
12136             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12137         else { /* we need to get it byte by byte */
12138             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12139             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12140             if (options.model == MODEL_FLAT24)
12141             {
12142                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12143             }
12144         }
12145     }
12146     /* so dptr know contains the address */
12147     pic16_freeAsmop(result,NULL,ic,TRUE);
12148     pic16_aopOp(right,ic,FALSE);
12149
12150     /* if bit then unpack */
12151     if (IS_BITFIELD(retype)) 
12152         genPackBits(retype,result,right,"dptr",FPOINTER);
12153     else {
12154         size = AOP_SIZE(right);
12155         offset = 0 ;
12156
12157         while (size--) {
12158             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12159             MOVA(l);
12160             pic16_emitcode("movx","@dptr,a");
12161             if (size)
12162                 pic16_emitcode("inc","dptr");
12163         }
12164     }
12165
12166     pic16_freeAsmop(right,NULL,ic,TRUE);
12167 }
12168 #endif
12169
12170 /*-----------------------------------------------------------------*/
12171 /* genGenPointerSet - set value from generic pointer space         */
12172 /*-----------------------------------------------------------------*/
12173 #if 0
12174 static void genGenPointerSet (operand *right,
12175                               operand *result, iCode *ic)
12176 {
12177         int i, size, offset, lit;
12178         sym_link *retype = getSpec(operandType(right));
12179
12180         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12181
12182         pic16_aopOp(result,ic,FALSE);
12183         pic16_aopOp(right,ic,FALSE);
12184         size = AOP_SIZE(right);
12185         offset = 0;
12186
12187         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12188
12189         /* if the operand is already in dptr 
12190                 then we do nothing else we move the value to dptr */
12191         if (AOP_TYPE(result) != AOP_STR) {
12192                 /* if this is remateriazable */
12193                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12194                 // WARNING: anythig until "else" is untested!
12195                 if (AOP_TYPE(result) == AOP_IMMD) {
12196                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12197                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12198                         // load FSR0 from immediate
12199                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12200                         offset = 0;
12201                         while(size--) {
12202                                 if(size) {
12203                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12204                                 } else {
12205                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12206                                 }
12207                                 offset++;
12208                         }
12209                         goto release;
12210                 }
12211                 else { /* we need to get it byte by byte */
12212                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12213                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12214
12215                         // set up FSR0 with address of result
12216                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12217                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12218
12219                         /* hack hack! see if this the FSR. If so don't load W */
12220                         if(AOP_TYPE(right) != AOP_ACC) {
12221
12222                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12223
12224                                 if(AOP_TYPE(right) == AOP_LIT)
12225                                 {
12226                                         // copy literal
12227                                         // note: pic16_popGet handles sign extension
12228                                         for(i=0;i<size;i++) {
12229                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12230                                                 if(i < size-1)
12231                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12232                                                 else
12233                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12234                                         }
12235                                 } else {
12236                                         // copy regs
12237
12238                                         for(i=0;i<size;i++) {
12239                                                 if(i < size-1)
12240                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12241                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12242                                                 else
12243                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12244                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12245                                         }
12246                                 }
12247                                 goto release;
12248                         } 
12249                         // right = ACC
12250                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12251                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12252                         goto release;
12253         } // if (AOP_TYPE(result) != AOP_IMMD)
12254
12255         } // if (AOP_TYPE(result) != AOP_STR)
12256         /* so dptr know contains the address */
12257
12258
12259         /* if bit then unpack */
12260         if (IS_BITFIELD(retype)) 
12261                 genPackBits(retype,result,right,"dptr",GPOINTER);
12262         else {
12263                 size = AOP_SIZE(right);
12264                 offset = 0 ;
12265
12266                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12267
12268                 // set up FSR0 with address of result
12269                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12270                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12271         
12272                 while (size--) {
12273                         if (AOP_TYPE(right) == AOP_LIT) {
12274                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12275                                 if (size) {
12276                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12277                                 } else {
12278                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12279                                 }
12280                         } else { // no literal
12281                                 if(size) {
12282                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12283                                 } else {
12284                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12285                                 }
12286                         }
12287                         offset++;
12288                 }
12289         }
12290
12291         release:
12292         pic16_freeAsmop(right,NULL,ic,TRUE);
12293         pic16_freeAsmop(result,NULL,ic,TRUE);
12294 }
12295 #endif
12296
12297 static void genGenPointerSet (operand *right,
12298                               operand *result, iCode *ic)
12299 {
12300   int size;
12301   sym_link *retype = getSpec(operandType(result));
12302
12303     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12304
12305     pic16_aopOp(result,ic,FALSE);
12306     pic16_aopOp(right,ic,FALSE);
12307     size = AOP_SIZE(right);
12308
12309     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12310
12311
12312     /* if bit then unpack */
12313     if (IS_BITFIELD(retype)) {
12314 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12315       genPackBits(retype,result,right,"dptr",GPOINTER);
12316       goto release;
12317     }
12318
12319     size = AOP_SIZE(right);
12320
12321     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12322
12323
12324     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12325
12326     /* value of right+0 is placed on stack, which will be retrieved
12327      * by the support function thus restoring the stack. The important
12328      * thing is that there is no need to manually restore stack pointer
12329      * here */
12330     pushaop(AOP(right), 0);
12331 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12332     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12333     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12334     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12335     
12336     /* load address to write to in WREG:FSR0H:FSR0L */
12337     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12338                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12339     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12340                                 pic16_popCopyReg(&pic16_pc_prodl)));
12341     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12342     
12343     pic16_callGenericPointerRW(1, size);
12344
12345 release:
12346     pic16_freeAsmop(right,NULL,ic,TRUE);
12347     pic16_freeAsmop(result,NULL,ic,TRUE);
12348 }
12349
12350 /*-----------------------------------------------------------------*/
12351 /* genPointerSet - stores the value into a pointer location        */
12352 /*-----------------------------------------------------------------*/
12353 static void genPointerSet (iCode *ic)
12354 {    
12355   operand *right, *result ;
12356   sym_link *type, *etype;
12357   int p_type;
12358
12359     FENTRY;
12360
12361     right = IC_RIGHT(ic);
12362     result = IC_RESULT(ic) ;
12363
12364     /* depending on the type of pointer we need to
12365     move it to the correct pointer register */
12366     type = operandType(result);
12367     etype = getSpec(type);
12368     
12369     /* if left is of type of pointer then it is simple */
12370     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12371         p_type = DCL_TYPE(type);
12372     }
12373     else {
12374         /* we have to go by the storage class */
12375         p_type = PTR_TYPE(SPEC_OCLS(etype));
12376
12377 /*      if (SPEC_OCLS(etype)->codesp ) { */
12378 /*          p_type = CPOINTER ;  */
12379 /*      } */
12380 /*      else */
12381 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12382 /*              p_type = FPOINTER ; */
12383 /*          else */
12384 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12385 /*                  p_type = PPOINTER ; */
12386 /*              else */
12387 /*                  if (SPEC_OCLS(etype) == idata ) */
12388 /*                      p_type = IPOINTER ; */
12389 /*                  else */
12390 /*                      p_type = POINTER ; */
12391     }
12392
12393     /* now that we have the pointer type we assign
12394     the pointer values */
12395     switch (p_type) {
12396       case POINTER:
12397       case FPOINTER:
12398       case IPOINTER:
12399         genNearPointerSet (right,result,ic);
12400         break;
12401
12402       case PPOINTER:
12403         genPagedPointerSet (right,result,ic);
12404         break;
12405
12406 #if 0
12407       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12408       case FPOINTER:
12409         genFarPointerSet (right,result,ic);
12410         break;
12411 #endif
12412         
12413       case GPOINTER:
12414         genGenPointerSet (right,result,ic);
12415         break;
12416
12417       default:
12418         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12419           "genPointerSet: illegal pointer type");
12420     }
12421 }
12422
12423 /*-----------------------------------------------------------------*/
12424 /* genIfx - generate code for Ifx statement                        */
12425 /*-----------------------------------------------------------------*/
12426 static void genIfx (iCode *ic, iCode *popIc)
12427 {
12428   operand *cond = IC_COND(ic);
12429   int isbit =0;
12430
12431     FENTRY;
12432
12433     pic16_aopOp(cond,ic,FALSE);
12434
12435     /* get the value into acc */
12436     if (AOP_TYPE(cond) != AOP_CRY)
12437       pic16_toBoolean(cond);
12438     else
12439       isbit = 1;
12440     /* the result is now in the accumulator */
12441     pic16_freeAsmop(cond,NULL,ic,TRUE);
12442
12443     /* if there was something to be popped then do it */
12444     if (popIc)
12445       genIpop(popIc);
12446
12447     /* if the condition is  a bit variable */
12448     if (isbit && IS_ITEMP(cond) && 
12449         SPIL_LOC(cond)) {
12450       genIfxJump(ic,"c");
12451       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12452     } else {
12453       if (isbit && !IS_ITEMP(cond))
12454         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12455         else
12456         genIfxJump(ic,"a");
12457     }
12458     ic->generated = 1;
12459 }
12460
12461 /*-----------------------------------------------------------------*/
12462 /* genAddrOf - generates code for address of                       */
12463 /*-----------------------------------------------------------------*/
12464 static void genAddrOf (iCode *ic)
12465 {
12466   operand *result, *left;
12467   int size;
12468   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12469   pCodeOp *pcop0, *pcop1, *pcop2;
12470
12471     FENTRY;
12472
12473     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12474
12475     sym = OP_SYMBOL( IC_LEFT(ic) );
12476     
12477     if(sym->onStack) {
12478       /* get address of symbol on stack */
12479       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12480 #if 0
12481       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12482                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12483 #endif
12484
12485       // operands on stack are accessible via "FSR2 + index" with index
12486       // starting at 2 for arguments and growing from 0 downwards for
12487       // local variables (index == 0 is not assigned so we add one here)
12488       {
12489         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12490
12491           if (soffs <= 0) {
12492             assert (soffs < 0);
12493             soffs++;
12494           } // if
12495
12496           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12497           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12498           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12499           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12500           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12501           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12502           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12503       }
12504
12505       goto release;
12506     }
12507         
12508 //      if(pic16_debug_verbose) {
12509 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12510 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12511 //      }
12512         
12513     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12514     size = AOP_SIZE(IC_RESULT(ic));
12515
12516     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12517     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12518     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12519         
12520     if (size == 3) {
12521       pic16_emitpcode(POC_MOVLW, pcop0);
12522       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12523       pic16_emitpcode(POC_MOVLW, pcop1);
12524       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12525       pic16_emitpcode(POC_MOVLW, pcop2);
12526       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12527     } else
12528     if (size == 2) {
12529       pic16_emitpcode(POC_MOVLW, pcop0);
12530       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12531       pic16_emitpcode(POC_MOVLW, pcop1);
12532     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12533     } else {
12534       pic16_emitpcode(POC_MOVLW, pcop0);
12535       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12536     }
12537
12538     pic16_freeAsmop(left, NULL, ic, FALSE);
12539 release:
12540     pic16_freeAsmop(result,NULL,ic,TRUE);
12541 }
12542
12543
12544 #if 0
12545 /*-----------------------------------------------------------------*/
12546 /* genFarFarAssign - assignment when both are in far space         */
12547 /*-----------------------------------------------------------------*/
12548 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12549 {
12550     int size = AOP_SIZE(right);
12551     int offset = 0;
12552     char *l ;
12553     /* first push the right side on to the stack */
12554     while (size--) {
12555         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12556         MOVA(l);
12557         pic16_emitcode ("push","acc");
12558     }
12559     
12560     pic16_freeAsmop(right,NULL,ic,FALSE);
12561     /* now assign DPTR to result */
12562     pic16_aopOp(result,ic,FALSE);
12563     size = AOP_SIZE(result);
12564     while (size--) {
12565         pic16_emitcode ("pop","acc");
12566         pic16_aopPut(AOP(result),"a",--offset);
12567     }
12568     pic16_freeAsmop(result,NULL,ic,FALSE);
12569         
12570 }
12571 #endif
12572
12573 /*-----------------------------------------------------------------*/
12574 /* genAssign - generate code for assignment                        */
12575 /*-----------------------------------------------------------------*/
12576 static void genAssign (iCode *ic)
12577 {
12578   operand *result, *right;
12579   sym_link *restype, *rtype;
12580   int size, offset,know_W;
12581   unsigned long lit = 0L;
12582
12583     result = IC_RESULT(ic);
12584     right  = IC_RIGHT(ic) ;
12585
12586     FENTRY;
12587   
12588     /* if they are the same */
12589     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12590       return ;
12591
12592     /* reversed order operands are aopOp'ed so that result operand
12593      * is effective in case right is a stack symbol. This maneauver
12594      * allows to use the _G.resDirect flag later */
12595      pic16_aopOp(result,ic,TRUE);
12596     pic16_aopOp(right,ic,FALSE);
12597
12598     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12599
12600     /* if they are the same registers */
12601     if (pic16_sameRegs(AOP(right),AOP(result)))
12602       goto release;
12603
12604     /* if the result is a bit */
12605     if (AOP_TYPE(result) == AOP_CRY) {
12606       /* if the right size is a literal then
12607          we know what the value is */
12608       if (AOP_TYPE(right) == AOP_LIT) {
12609           
12610         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12611             pic16_popGet(AOP(result),0));
12612
12613         if (((int) operandLitValue(right))) 
12614           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12615               AOP(result)->aopu.aop_dir,
12616               AOP(result)->aopu.aop_dir);
12617         else
12618           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12619               AOP(result)->aopu.aop_dir,
12620               AOP(result)->aopu.aop_dir);
12621         
12622         goto release;
12623       }
12624
12625       /* the right is also a bit variable */
12626       if (AOP_TYPE(right) == AOP_CRY) {
12627         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12628         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12629         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12630
12631         goto release ;
12632       }
12633
12634       /* we need to or */
12635       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12636       pic16_toBoolean(right);
12637       emitSKPZ;
12638       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12639       //pic16_aopPut(AOP(result),"a",0);
12640       goto release ;
12641     }
12642
12643     /* bit variables done */
12644     /* general case */
12645     size = AOP_SIZE(result);
12646     offset = 0 ;
12647
12648   /* bit variables done */
12649   /* general case */
12650   size = AOP_SIZE(result);
12651   restype = operandType(result);
12652   rtype = operandType(right);
12653   offset = 0 ;
12654
12655   if(AOP_TYPE(right) == AOP_LIT) {
12656     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12657     {
12658       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12659
12660       /* patch tag for literals that are cast to pointers */
12661       if (IS_CODEPTR(restype)) {
12662         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12663         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12664       } else {
12665         if (IS_GENPTR(restype))
12666         {
12667           if (IS_CODEPTR(rtype)) {
12668             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12669             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12670           } else if (PIC_IS_DATA_PTR(rtype)) {
12671             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12672             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12673           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12674             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12675           } else if (IS_PTR(rtype)) {
12676             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12677             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12678           }
12679         }
12680       }
12681     } else {
12682       union {
12683         unsigned long lit_int;
12684         float lit_float;
12685       } info;
12686
12687
12688       if(IS_FIXED16X16(operandType(right))) {
12689         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12690       } else {
12691         /* take care if literal is a float */
12692         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12693         lit = info.lit_int;
12694       }
12695     }
12696   }
12697
12698 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12699 //                      sizeof(unsigned long int), sizeof(float));
12700
12701
12702     if (AOP_TYPE(right) == AOP_REG) {
12703       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12704       while (size--) {
12705         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12706       } // while
12707       goto release;
12708     }
12709
12710     /* when do we have to read the program memory?
12711      * - if right itself is a symbol in code space
12712      *   (we don't care what it points to if it's a pointer)
12713      * - AND right is not a function (we would want its address)
12714      */
12715     if(AOP_TYPE(right) != AOP_LIT
12716       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12717       && !IS_FUNC(OP_SYM_TYPE(right))
12718       && !IS_ITEMP(right)) {
12719
12720       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12721       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12722       
12723       // set up table pointer
12724       if(is_LitOp(right)) {
12725 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12726         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12727         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12728         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12729         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12730         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12731         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12732       } else {
12733 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12734         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12735             pic16_popCopyReg(&pic16_pc_tblptrl)));
12736         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12737             pic16_popCopyReg(&pic16_pc_tblptrh)));
12738         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12739             pic16_popCopyReg(&pic16_pc_tblptru)));
12740       }
12741
12742       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12743       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12744       while(size--) {
12745         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12746         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12747             pic16_popGet(AOP(result),offset)));
12748         offset++;
12749       }
12750
12751       /* FIXME: for pointers we need to extend differently (according
12752        * to pointer type DATA/CODE/EEPROM/... :*/
12753       size = getSize(OP_SYM_TYPE(right));
12754       if(AOP_SIZE(result) > size) {
12755         size = AOP_SIZE(result) - size;
12756         while(size--) {
12757           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12758           offset++;
12759         }
12760       }
12761       goto release;
12762     }
12763
12764 #if 0
12765     /* VR - What is this?! */
12766     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12767       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12768       
12769       if(aopIdx(AOP(result),0) == 4) {
12770         /* this is a workaround to save value of right into wreg too,
12771          * value of wreg is going to be used later */
12772         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12773         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12774         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12775         goto release;
12776       } else
12777 //      assert(0);
12778       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12779     }
12780 #endif
12781
12782     size = AOP_SIZE(right);
12783     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12784     know_W=-1;
12785     while (size--) {
12786       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12787       if(AOP_TYPE(right) == AOP_LIT) {
12788         if(lit&0xff) {
12789           if(know_W != (lit&0xff))
12790             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12791           know_W = lit&0xff;
12792           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12793         } else
12794           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12795
12796         lit >>= 8;
12797
12798       } else if (AOP_TYPE(right) == AOP_CRY) {
12799         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12800         if(offset == 0) {
12801           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12802           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12803           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12804         }
12805       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12806         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12807         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12808       } else {
12809         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12810
12811         if(!_G.resDirect) {                                             /* use this aopForSym feature */
12812           if(AOP_TYPE(result) == AOP_ACC) {
12813             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12814           } else
12815             if(AOP_TYPE(right) == AOP_ACC) {
12816               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12817             } else {
12818               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12819             }
12820         }
12821       }
12822
12823       offset++;
12824     }
12825     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12826   
12827 release:
12828   pic16_freeAsmop (right,NULL,ic,FALSE);
12829   pic16_freeAsmop (result,NULL,ic,TRUE);
12830
12831
12832 /*-----------------------------------------------------------------*/
12833 /* genJumpTab - generates code for jump table                       */
12834 /*-----------------------------------------------------------------*/
12835 static void genJumpTab (iCode *ic)
12836 {
12837   symbol *jtab;
12838   char *l;
12839   pCodeOp *jt_offs;
12840   pCodeOp *jt_offs_hi;
12841   pCodeOp *jt_label;
12842
12843     FENTRY;
12844
12845     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12846     /* get the condition into accumulator */
12847     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12848     MOVA(l);
12849     /* multiply by three */
12850     pic16_emitcode("add","a,acc");
12851     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12852
12853     jtab = newiTempLabel(NULL);
12854     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12855     pic16_emitcode("jmp","@a+dptr");
12856     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12857
12858 #if 0
12859     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12860     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12861     emitSKPNC;
12862     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12863     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12864     pic16_emitpLabel(jtab->key);
12865
12866 #else
12867
12868     jt_offs = pic16_popGetTempReg(0);
12869     jt_offs_hi = pic16_popGetTempReg(1);
12870     jt_label = pic16_popGetLabel (jtab->key);
12871     //fprintf (stderr, "Creating jump table...\n");
12872
12873     // calculate offset into jump table (idx * sizeof (GOTO))
12874     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12875     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12876     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12877     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12878     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12879     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12880     pic16_emitpcode(POC_MOVWF , jt_offs);
12881
12882     // prepare PCLATx (set to first entry in jump table)
12883     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12884     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12885     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12886     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12887     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12888
12889     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12890     pic16_emitpcode(POC_ADDWF , jt_offs);
12891     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12892     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12893     emitSKPNC;
12894     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12895
12896     // release temporaries and prepare jump into table (new PCL --> WREG)
12897     pic16_emitpcode(POC_MOVFW , jt_offs);
12898     pic16_popReleaseTempReg (jt_offs_hi, 1);
12899     pic16_popReleaseTempReg (jt_offs, 0);
12900
12901     // jump into the table
12902     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12903
12904     pic16_emitpLabelFORCE(jtab->key);
12905 #endif
12906
12907     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12908 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12909
12910     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12911     /* now generate the jump labels */
12912     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12913          jtab = setNextItem(IC_JTLABELS(ic))) {
12914 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12915         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12916         
12917     }
12918     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12919
12920 }
12921
12922 /*-----------------------------------------------------------------*/
12923 /* genMixedOperation - gen code for operators between mixed types  */
12924 /*-----------------------------------------------------------------*/
12925 /*
12926   TSD - Written for the PIC port - but this unfortunately is buggy.
12927   This routine is good in that it is able to efficiently promote 
12928   types to different (larger) sizes. Unfortunately, the temporary
12929   variables that are optimized out by this routine are sometimes
12930   used in other places. So until I know how to really parse the 
12931   iCode tree, I'm going to not be using this routine :(.
12932 */
12933 static int genMixedOperation (iCode *ic)
12934 {
12935 #if 0
12936   operand *result = IC_RESULT(ic);
12937   sym_link *ctype = operandType(IC_LEFT(ic));
12938   operand *right = IC_RIGHT(ic);
12939   int ret = 0;
12940   int big,small;
12941   int offset;
12942
12943   iCode *nextic;
12944   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12945
12946   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12947
12948   nextic = ic->next;
12949   if(!nextic)
12950     return 0;
12951
12952   nextright = IC_RIGHT(nextic);
12953   nextleft  = IC_LEFT(nextic);
12954   nextresult = IC_RESULT(nextic);
12955
12956   pic16_aopOp(right,ic,FALSE);
12957   pic16_aopOp(result,ic,FALSE);
12958   pic16_aopOp(nextright,  nextic, FALSE);
12959   pic16_aopOp(nextleft,   nextic, FALSE);
12960   pic16_aopOp(nextresult, nextic, FALSE);
12961
12962   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12963
12964     operand *t = right;
12965     right = nextright;
12966     nextright = t; 
12967
12968     pic16_emitcode(";remove right +","");
12969
12970   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12971 /*
12972     operand *t = right;
12973     right = nextleft;
12974     nextleft = t; 
12975 */
12976     pic16_emitcode(";remove left +","");
12977   } else
12978     return 0;
12979
12980   big = AOP_SIZE(nextleft);
12981   small = AOP_SIZE(nextright);
12982
12983   switch(nextic->op) {
12984
12985   case '+':
12986     pic16_emitcode(";optimize a +","");
12987     /* if unsigned or not an integral type */
12988     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12989       pic16_emitcode(";add a bit to something","");
12990     } else {
12991
12992       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12993
12994       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12995         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12996         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12997       } else
12998         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12999
13000       offset = 0;
13001       while(--big) {
13002
13003         offset++;
13004
13005         if(--small) {
13006           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13007             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13008             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13009           }
13010
13011           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13012           emitSKPNC;
13013           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13014                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13015                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13016           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13017           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13018
13019         } else {
13020           pic16_emitcode("rlf","known_zero,w");
13021
13022           /*
13023             if right is signed
13024               btfsc  right,7
13025                addlw ff
13026           */
13027           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13028             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13029             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13030           } else {
13031             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13032           }
13033         }
13034       }
13035       ret = 1;
13036     }
13037   }
13038   ret = 1;
13039
13040 release:
13041   pic16_freeAsmop(right,NULL,ic,TRUE);
13042   pic16_freeAsmop(result,NULL,ic,TRUE);
13043   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13044   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13045   if(ret)
13046     nextic->generated = 1;
13047
13048   return ret;
13049 #else
13050   return 0;
13051 #endif
13052 }
13053 /*-----------------------------------------------------------------*/
13054 /* genCast - gen code for casting                                  */
13055 /*-----------------------------------------------------------------*/
13056 static void genCast (iCode *ic)
13057 {
13058   operand *result = IC_RESULT(ic);
13059   sym_link *ctype = operandType(IC_LEFT(ic));
13060   sym_link *rtype = operandType(IC_RIGHT(ic));
13061   sym_link *restype = operandType(IC_RESULT(ic));
13062   operand *right = IC_RIGHT(ic);
13063   int size, offset ;
13064
13065
13066     FENTRY;
13067
13068         /* if they are equivalent then do nothing */
13069 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13070 //              return ;
13071
13072         pic16_aopOp(result,ic,FALSE);
13073         pic16_aopOp(right,ic,FALSE) ;
13074
13075         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13076
13077
13078         /* if the result is a bit */
13079         if (AOP_TYPE(result) == AOP_CRY) {
13080         
13081                 /* if the right size is a literal then
13082                  * we know what the value is */
13083                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13084
13085                 if (AOP_TYPE(right) == AOP_LIT) {
13086                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13087                                 pic16_popGet(AOP(result),0));
13088
13089                         if (((int) operandLitValue(right))) 
13090                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13091                                         AOP(result)->aopu.aop_dir,
13092                                         AOP(result)->aopu.aop_dir);
13093                         else
13094                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13095                                         AOP(result)->aopu.aop_dir,
13096                                         AOP(result)->aopu.aop_dir);
13097                         goto release;
13098                 }
13099
13100                 /* the right is also a bit variable */
13101                 if (AOP_TYPE(right) == AOP_CRY) {
13102                         emitCLRC;
13103                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13104
13105                         pic16_emitcode("clrc","");
13106                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13107                                 AOP(right)->aopu.aop_dir,
13108                                 AOP(right)->aopu.aop_dir);
13109                         pic16_aopPut(AOP(result),"c",0);
13110                         goto release ;
13111                 }
13112
13113                 /* we need to or */
13114                 if (AOP_TYPE(right) == AOP_REG) {
13115                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13116                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13117                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13118                 }
13119                 pic16_toBoolean(right);
13120                 pic16_aopPut(AOP(result),"a",0);
13121                 goto release ;
13122         }
13123
13124         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13125           int offset = 1;
13126
13127                 size = AOP_SIZE(result);
13128
13129                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13130
13131                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13132                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13133                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13134
13135                 while (size--)
13136                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13137
13138                 goto release;
13139         }
13140
13141         if(IS_BITFIELD(getSpec(restype))
13142           && IS_BITFIELD(getSpec(rtype))) {
13143           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13144         }
13145         
13146         /* port from pic14 to cope with generic pointers */
13147         if (PIC_IS_TAGGED(restype))
13148         {
13149           operand *result = IC_RESULT(ic);
13150           //operand *left = IC_LEFT(ic);
13151           operand *right = IC_RIGHT(ic);
13152           int tag = 0xff;
13153
13154           /* copy common part */
13155           int max, size = AOP_SIZE(result);
13156           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13157           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13158
13159           max = size;
13160           while (size--)
13161           {
13162             pic16_mov2w (AOP(right), size);
13163             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13164           } // while
13165
13166           /* upcast into generic pointer type? */
13167           if (IS_GENPTR(restype)
13168               && !PIC_IS_TAGGED(rtype)
13169               && (AOP_SIZE(result) > max))
13170           {
13171             /* determine appropriate tag for right */
13172             if (PIC_IS_DATA_PTR(rtype))
13173               tag = GPTR_TAG_DATA;
13174             else if (IS_CODEPTR(rtype))
13175               tag = GPTR_TAG_CODE;
13176             else if (PIC_IS_DATA_PTR(ctype)) {
13177               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13178               tag = GPTR_TAG_DATA;
13179             } else if (IS_CODEPTR(ctype)) {
13180               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13181               tag = GPTR_TAG_CODE;
13182             } else if (IS_PTR(rtype)) {
13183               PERFORM_ONCE(weirdcast,
13184               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
13185               );
13186               tag = GPTR_TAG_DATA;
13187             } else {
13188               PERFORM_ONCE(weirdcast,
13189               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
13190               );
13191               tag = GPTR_TAG_DATA;
13192             }
13193
13194             assert (AOP_SIZE(result) == 3);
13195             /* zero-extend address... */
13196             for (size = max; size < AOP_SIZE(result)-1; size++)
13197               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13198             /* ...and add tag */
13199             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13200           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13201             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13202             for (size = max; size < AOP_SIZE(result)-1; size++)
13203               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13204             /* add __code tag */
13205             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13206           } else if (AOP_SIZE(result) > max) {
13207             /* extend non-pointers */
13208             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13209             pic16_addSign(result, max, 0);
13210           } // if
13211           goto release;
13212         }
13213
13214         /* if they are the same size : or less */
13215         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13216
13217                 /* if they are in the same place */
13218                 if (pic16_sameRegs(AOP(right),AOP(result)))
13219                         goto release;
13220
13221                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13222 #if 0
13223                 if (IS_PTR_CONST(rtype))
13224 #else
13225                 if (IS_CODEPTR(rtype))
13226 #endif
13227                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13228
13229 #if 0
13230                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13231 #else
13232                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13233 #endif
13234                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13235
13236 #if 0
13237                 if(AOP_TYPE(right) == AOP_IMMD) {
13238                   pCodeOp *pcop0, *pcop1, *pcop2;
13239                   symbol *sym = OP_SYMBOL( right );
13240
13241                         size = AOP_SIZE(result);
13242                         /* low */
13243                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13244                         /* high */
13245                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13246                         /* upper */
13247                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13248         
13249                         if (size == 3) {
13250                                 pic16_emitpcode(POC_MOVLW, pcop0);
13251                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13252                                 pic16_emitpcode(POC_MOVLW, pcop1);
13253                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13254                                 pic16_emitpcode(POC_MOVLW, pcop2);
13255                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13256                         } else
13257                         if (size == 2) {
13258                                 pic16_emitpcode(POC_MOVLW, pcop0);
13259                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13260                                 pic16_emitpcode(POC_MOVLW, pcop1);
13261                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13262                         } else {
13263                                 pic16_emitpcode(POC_MOVLW, pcop0);
13264                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13265                         }
13266                 } else
13267 #endif
13268                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13269                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13270                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13271
13272                         if(AOP_SIZE(result) < 2) {
13273                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13274                         } else {
13275                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13276                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13277                         }
13278                 } else {
13279                         /* if they in different places then copy */
13280                         size = AOP_SIZE(result);
13281                         offset = 0 ;
13282                         while (size--) {
13283                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13284                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13285                                 offset++;
13286                         }
13287                 }
13288                 goto release;
13289         }
13290
13291         /* if the result is of type pointer */
13292         if (IS_PTR(ctype)) {
13293           int p_type;
13294           sym_link *type = operandType(right);
13295           sym_link *etype = getSpec(type);
13296
13297                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13298
13299                 /* pointer to generic pointer */
13300                 if (IS_GENPTR(ctype)) {
13301                   char *l = zero;
13302             
13303                         if (IS_PTR(type)) 
13304                                 p_type = DCL_TYPE(type);
13305                         else {
13306                 /* we have to go by the storage class */
13307                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13308
13309 /*              if (SPEC_OCLS(etype)->codesp )  */
13310 /*                  p_type = CPOINTER ;  */
13311 /*              else */
13312 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13313 /*                      p_type = FPOINTER ; */
13314 /*                  else */
13315 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13316 /*                          p_type = PPOINTER; */
13317 /*                      else */
13318 /*                          if (SPEC_OCLS(etype) == idata ) */
13319 /*                              p_type = IPOINTER ; */
13320 /*                          else */
13321 /*                              p_type = POINTER ; */
13322             }
13323                 
13324             /* the first two bytes are known */
13325       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13326             size = GPTRSIZE - 1; 
13327             offset = 0 ;
13328             while (size--) {
13329               if(offset < AOP_SIZE(right)) {
13330                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13331                 pic16_mov2f(AOP(result), AOP(right), offset);
13332 /*
13333                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13334                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13335                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13336                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13337                 } else { 
13338                   
13339                   pic16_aopPut(AOP(result),
13340                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13341                          offset);
13342                 }
13343 */
13344               } else 
13345                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13346               offset++;
13347             }
13348             /* the last byte depending on type */
13349             switch (p_type) {
13350             case IPOINTER:
13351             case POINTER:
13352             case FPOINTER:
13353                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13354                 break;
13355
13356             case CPOINTER:
13357                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13358                 break;
13359
13360             case PPOINTER:
13361               pic16_emitcode(";BUG!? ","%d",__LINE__);
13362                 l = "#0x03";
13363                 break;
13364
13365             case GPOINTER:
13366                 if (GPTRSIZE > AOP_SIZE(right)) {
13367                   // assume __data pointer... THIS MIGHT BE WRONG!
13368                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13369                 } else {
13370                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13371                 }
13372               break;
13373               
13374             default:
13375                 /* this should never happen */
13376                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13377                        "got unknown pointer type");
13378                 exit(1);
13379             }
13380             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13381             goto release ;
13382         }
13383         
13384         
13385         assert( 0 );
13386         /* just copy the pointers */
13387         size = AOP_SIZE(result);
13388         offset = 0 ;
13389         while (size--) {
13390             pic16_aopPut(AOP(result),
13391                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13392                    offset);
13393             offset++;
13394         }
13395         goto release ;
13396     }
13397     
13398
13399
13400     /* so we now know that the size of destination is greater
13401     than the size of the source.
13402     Now, if the next iCode is an operator then we might be
13403     able to optimize the operation without performing a cast.
13404     */
13405     if(genMixedOperation(ic))
13406       goto release;
13407
13408     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13409     
13410     /* we move to result for the size of source */
13411     size = AOP_SIZE(right);
13412     offset = 0 ;
13413
13414     while (size--) {
13415       if(!_G.resDirect)
13416         pic16_mov2f(AOP(result), AOP(right), offset);
13417       offset++;
13418     }
13419
13420     /* now depending on the sign of the destination */
13421     size = AOP_SIZE(result) - AOP_SIZE(right);
13422     /* if unsigned or not an integral type */
13423     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13424       while (size--)
13425         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13426     } else {
13427       /* we need to extend the sign :( */
13428
13429       if(size == 1) {
13430         /* Save one instruction of casting char to int */
13431         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13432         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13433         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13434       } else {
13435         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13436
13437         if(offset)
13438           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13439         else
13440           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13441         
13442         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13443
13444         while (size--)
13445           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13446       }
13447     }
13448
13449 release:
13450     pic16_freeAsmop(right,NULL,ic,TRUE);
13451     pic16_freeAsmop(result,NULL,ic,TRUE);
13452
13453 }
13454
13455 /*-----------------------------------------------------------------*/
13456 /* genDjnz - generate decrement & jump if not zero instrucion      */
13457 /*-----------------------------------------------------------------*/
13458 static int genDjnz (iCode *ic, iCode *ifx)
13459 {
13460     symbol *lbl, *lbl1;
13461     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13462
13463     if (!ifx)
13464         return 0;
13465     
13466     /* if the if condition has a false label
13467        then we cannot save */
13468     if (IC_FALSE(ifx))
13469         return 0;
13470
13471     /* if the minus is not of the form 
13472        a = a - 1 */
13473     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13474         !IS_OP_LITERAL(IC_RIGHT(ic)))
13475         return 0;
13476
13477     if (operandLitValue(IC_RIGHT(ic)) != 1)
13478         return 0;
13479
13480     /* if the size of this greater than one then no
13481        saving */
13482     if (getSize(operandType(IC_RESULT(ic))) > 1)
13483         return 0;
13484
13485     /* otherwise we can save BIG */
13486     lbl = newiTempLabel(NULL);
13487     lbl1= newiTempLabel(NULL);
13488
13489     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13490     
13491     if (IS_AOP_PREG(IC_RESULT(ic))) {
13492         pic16_emitcode("dec","%s",
13493                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13494         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13495         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13496     } else {    
13497
13498
13499       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13500       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13501
13502       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13503       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13504
13505     }
13506     
13507     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13508     ifx->generated = 1;
13509     return 1;
13510 }
13511
13512 /*-----------------------------------------------------------------*/
13513 /* genReceive - generate code for a receive iCode                  */
13514 /*-----------------------------------------------------------------*/
13515 static void genReceive (iCode *ic)
13516 {    
13517
13518   FENTRY;
13519
13520 #if 0
13521   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13522         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13523 #endif
13524 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13525
13526   if (isOperandInFarSpace(IC_RESULT(ic))
13527       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13528           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13529
13530     int size = getSize(operandType(IC_RESULT(ic)));
13531     int offset =  pic16_fReturnSizePic - size;
13532
13533       assert( 0 );
13534       while (size--) {
13535         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13536                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13537                       offset++;
13538         }
13539
13540       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13541
13542       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13543       size = AOP_SIZE(IC_RESULT(ic));
13544       offset = 0;
13545       while (size--) {
13546         pic16_emitcode ("pop","acc");
13547         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13548       }
13549   } else {
13550     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13551     _G.accInUse++;
13552     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13553     _G.accInUse--;
13554
13555     /* set pseudo stack pointer to where it should be - dw*/
13556     GpsuedoStkPtr = ic->parmBytes;
13557
13558     /* setting GpsuedoStkPtr has side effects here: */
13559     /* FIXME: What's the correct size of the return(ed) value?
13560      *        For now, assuming '4' as before... */
13561     assignResultValue(IC_RESULT(ic), 4, 0);
13562   }
13563
13564   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13565 }
13566
13567 /*-----------------------------------------------------------------*/
13568 /* genDummyRead - generate code for dummy read of volatiles        */
13569 /*-----------------------------------------------------------------*/
13570 static void
13571 genDummyRead (iCode * ic)
13572 {
13573   operand *op;
13574   int i;
13575
13576   op = IC_RIGHT(ic);
13577   if (op && IS_SYMOP(op)) {
13578     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13579       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13580       return;
13581     }
13582     pic16_aopOp (op, ic, FALSE);
13583     for (i=0; i < AOP_SIZE(op); i++) {
13584       // may need to protect this from the peepholer -- this is not nice but works...
13585       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13586       pic16_mov2w (AOP(op),i);
13587       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13588     } // for i
13589     pic16_freeAsmop (op, NULL, ic, TRUE);
13590   } else if (op) {
13591     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13592   } // if
13593 }
13594
13595 /*-----------------------------------------------------------------*/
13596 /* genpic16Code - generate code for pic16 based controllers        */
13597 /*-----------------------------------------------------------------*/
13598 /*
13599  * At this point, ralloc.c has gone through the iCode and attempted
13600  * to optimize in a way suitable for a PIC. Now we've got to generate
13601  * PIC instructions that correspond to the iCode.
13602  *
13603  * Once the instructions are generated, we'll pass through both the
13604  * peep hole optimizer and the pCode optimizer.
13605  *-----------------------------------------------------------------*/
13606
13607 void genpic16Code (iCode *lic)
13608 {
13609   iCode *ic;
13610   int cln = 0;
13611
13612     lineHead = lineCurr = NULL;
13613
13614     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13615     pic16_addpBlock(pb);
13616
13617 #if 0
13618     /* if debug information required */
13619     if (options.debug && currFunc) {
13620       if (currFunc) {
13621         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13622       }
13623     }
13624 #endif
13625
13626     for (ic = lic ; ic ; ic = ic->next ) {
13627
13628       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13629       if ( cln != ic->lineno ) {
13630         if ( options.debug ) {
13631           debugFile->writeCLine (ic);
13632         }
13633         
13634         if(!options.noCcodeInAsm) {
13635           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13636               printCLine(ic->filename, ic->lineno)));
13637         }
13638
13639         cln = ic->lineno ;
13640       }
13641         
13642       if(options.iCodeInAsm) {
13643         char *iLine;
13644
13645           /* insert here code to print iCode as comment */
13646           iLine = printILine(ic);
13647           pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13648           dbuf_free(iLine);
13649       }
13650
13651       /* if the result is marked as
13652        * spilt and rematerializable or code for
13653        * this has already been generated then
13654        * do nothing */
13655       if (resultRemat(ic) || ic->generated ) 
13656         continue ;
13657         
13658       /* depending on the operation */
13659       switch (ic->op) {
13660         case '!' :
13661           pic16_genNot(ic);
13662           break;
13663             
13664         case '~' :
13665           pic16_genCpl(ic);
13666           break;
13667             
13668         case UNARYMINUS:
13669           genUminus (ic);
13670           break;
13671             
13672         case IPUSH:
13673           genIpush (ic);
13674           break;
13675             
13676         case IPOP:
13677           /* IPOP happens only when trying to restore a 
13678            * spilt live range, if there is an ifx statement
13679            * following this pop then the if statement might
13680            * be using some of the registers being popped which
13681            * would destroy the contents of the register so
13682            * we need to check for this condition and handle it */
13683            if (ic->next
13684              && ic->next->op == IFX
13685              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13686                genIfx (ic->next,ic);
13687           else
13688             genIpop (ic);
13689           break; 
13690             
13691         case CALL:
13692           genCall (ic);
13693           break;
13694             
13695         case PCALL:
13696           genPcall (ic);
13697           break;
13698             
13699         case FUNCTION:
13700           genFunction (ic);
13701           break;
13702             
13703         case ENDFUNCTION:
13704           genEndFunction (ic);
13705           break;
13706             
13707         case RETURN:
13708           genRet (ic);
13709           break;
13710             
13711         case LABEL:
13712           genLabel (ic);
13713           break;
13714             
13715         case GOTO:
13716           genGoto (ic);
13717           break;
13718             
13719         case '+' :
13720           pic16_genPlus (ic) ;
13721           break;
13722             
13723         case '-' :
13724           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13725             pic16_genMinus (ic);
13726           break;
13727
13728         case '*' :
13729           genMult (ic);
13730           break;
13731             
13732         case '/' :
13733           genDiv (ic) ;
13734           break;
13735             
13736         case '%' :
13737           genMod (ic);
13738           break;
13739             
13740         case '>' :
13741           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13742           break;
13743             
13744         case '<' :
13745           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13746           break;
13747             
13748         case LE_OP:
13749         case GE_OP:
13750         case NE_OP:
13751           /* note these two are xlated by algebraic equivalence
13752            * during parsing SDCC.y */
13753           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13754             "got '>=' or '<=' shouldn't have come here");
13755           break;
13756
13757         case EQ_OP:
13758           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13759           break;            
13760             
13761         case AND_OP:
13762           genAndOp (ic);
13763           break;
13764             
13765         case OR_OP:
13766           genOrOp (ic);
13767           break;
13768             
13769         case '^' :
13770           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13771           break;
13772             
13773         case '|' :
13774           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13775           break;
13776             
13777         case BITWISEAND:
13778           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13779           break;
13780             
13781         case INLINEASM:
13782           genInline (ic);
13783           break;
13784             
13785         case RRC:
13786           genRRC (ic);
13787           break;
13788             
13789         case RLC:
13790           genRLC (ic);
13791           break;
13792             
13793         case GETHBIT:
13794           genGetHbit (ic);
13795           break;
13796             
13797         case LEFT_OP:
13798           genLeftShift (ic);
13799           break;
13800             
13801         case RIGHT_OP:
13802           genRightShift (ic);
13803           break;
13804             
13805         case GET_VALUE_AT_ADDRESS:
13806           genPointerGet(ic);
13807           break;
13808             
13809         case '=' :
13810           if (POINTER_SET(ic))
13811             genPointerSet(ic);
13812           else
13813             genAssign(ic);
13814           break;
13815             
13816         case IFX:
13817           genIfx (ic,NULL);
13818           break;
13819             
13820         case ADDRESS_OF:
13821           genAddrOf (ic);
13822           break;
13823             
13824         case JUMPTABLE:
13825           genJumpTab (ic);
13826           break;
13827             
13828         case CAST:
13829           genCast (ic);
13830           break;
13831             
13832         case RECEIVE:
13833           genReceive(ic);
13834           break;
13835             
13836         case SEND:
13837           addSet(&_G.sendSet,ic);
13838           break;
13839
13840         case DUMMY_READ_VOLATILE:
13841           genDummyRead (ic);
13842           break;
13843
13844         default :
13845           ic = ic;
13846       }
13847     }
13848
13849
13850     /* now we are ready to call the
13851        peep hole optimizer */
13852     if (!options.nopeep)
13853       peepHole (&lineHead);
13854
13855     /* now do the actual printing */
13856     printLine (lineHead, codeOutBuf);
13857
13858 #ifdef PCODE_DEBUG
13859     DFPRINTF((stderr,"printing pBlock\n\n"));
13860     pic16_printpBlock(stdout,pb);
13861 #endif
13862
13863     return;
13864 }
13865