* src/pic16/glue.c,
[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 0
3602 /*-----------------------------------------------------------------*/
3603 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3604 /*-----------------------------------------------------------------*/
3605 static bool inExcludeList(char *s)
3606 {
3607   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3608     int i =0;
3609     
3610     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3611     if (options.excludeRegs[i] &&
3612     STRCASECMP(options.excludeRegs[i],"none") == 0)
3613         return FALSE ;
3614
3615     for ( i = 0 ; options.excludeRegs[i]; i++) {
3616         if (options.excludeRegs[i] &&
3617         STRCASECMP(s,options.excludeRegs[i]) == 0)
3618             return TRUE;
3619     }
3620     return FALSE ;
3621 }
3622 #endif
3623
3624 /*-----------------------------------------------------------------*/
3625 /* genFunction - generated code for function entry                 */
3626 /*-----------------------------------------------------------------*/
3627 static void genFunction (iCode *ic)
3628 {
3629   symbol *sym;
3630   sym_link *ftype;
3631   
3632     FENTRY;
3633     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3634
3635     pic16_labelOffset += (max_key+4);
3636     max_key=0;
3637     GpsuedoStkPtr=0;
3638     _G.nRegsSaved = 0;
3639         
3640     ftype = operandType(IC_LEFT(ic));
3641     sym = OP_SYMBOL(IC_LEFT(ic));
3642
3643     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3644       /* create an absolute section at the interrupt vector:
3645        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3646       symbol *asym;
3647       char asymname[128];
3648       pBlock *apb;
3649
3650 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3651
3652         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3653           sprintf(asymname, "ivec_%s", sym->name);
3654         else
3655           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3656   
3657         /* when an interrupt is declared as naked, do not emit the special
3658          * wrapper segment at vector address. The user should take care for
3659          * this instead. -- VR */
3660
3661         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3662           asym = newSymbol(asymname, 0);
3663           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3664           pic16_addpBlock( apb );
3665
3666           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3667           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3668           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3669           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3670           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3671                 
3672           /* mark the end of this tiny function */
3673           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3674         } else {
3675           sprintf(asymname, "%s", sym->rname);
3676         }
3677
3678         {
3679           absSym *abSym;
3680
3681             abSym = Safe_calloc(1, sizeof(absSym));
3682             strcpy(abSym->name, asymname);
3683
3684             switch( FUNC_INTNO(sym->type) ) {
3685               case 0: abSym->address = 0x000000; break;
3686               case 1: abSym->address = 0x000008; break;
3687               case 2: abSym->address = 0x000018; break;
3688               
3689               default:
3690 //                fprintf(stderr, "no interrupt number is given\n");
3691                 abSym->address = -1; break;
3692             }
3693
3694             /* relocate interrupt vectors if needed */
3695             if(abSym->address != -1)
3696               abSym->address += pic16_options.ivt_loc;
3697
3698             addSet(&absSymSet, abSym);
3699         }
3700     }
3701
3702     /* create the function header */
3703     pic16_emitcode(";","-----------------------------------------");
3704     pic16_emitcode(";"," function %s",sym->name);
3705     pic16_emitcode(";","-----------------------------------------");
3706
3707     /* prevent this symbol from being emitted as 'extern' */
3708     pic16_stringInSet(sym->rname, &pic16_localFunctions, 1);
3709
3710     pic16_emitcode("","%s:",sym->rname);
3711     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3712
3713     {
3714       absSym *ab;
3715
3716         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3717           if(!strcmp(ab->name, sym->rname)) {
3718             pic16_pBlockConvert2Absolute(pb);
3719             break;
3720           }
3721         }
3722     }
3723
3724     if(IFFUNC_ISNAKED(ftype)) {
3725       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3726       return;
3727     }
3728         
3729     /* if critical function then turn interrupts off */
3730     if (IFFUNC_ISCRITICAL(ftype)) {
3731       //pic16_emitcode("clr","ea");
3732     }
3733
3734     currFunc = sym;             /* update the currFunc symbol */
3735     _G.fregsUsed = sym->regsUsed;
3736     _G.sregsAlloc = newBitVect(128);
3737     
3738
3739     /* if this is an interrupt service routine then
3740      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3741     if (IFFUNC_ISISR(sym->type)) {
3742         _G.usefastretfie = 1;   /* use shadow registers by default */
3743         
3744         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3745         if(!FUNC_ISSHADOWREGS(sym->type)) {
3746           /* do not save WREG,STATUS,BSR for high priority interrupts
3747            * because they are stored in the hardware shadow registers already */
3748           _G.usefastretfie = 0;
3749           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3750           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3751           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3752         }
3753
3754         /* these should really be optimized somehow, because not all
3755          * interrupt handlers modify them */
3756         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3757         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3758         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3759         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3760         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3761         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3762         
3763 //        pic16_pBlockConvert2ISR(pb);
3764     }
3765
3766     /* emit code to setup stack frame if user enabled,
3767      * and function is not main() */
3768     
3769 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3770     if(strcmp(sym->name, "main")) {
3771       if(0 
3772         || !options.ommitFramePtr 
3773 //        || sym->regsUsed
3774         || IFFUNC_ARGS(sym->type)
3775         || FUNC_HASSTACKPARM(sym->etype)
3776         ) {
3777         /* setup the stack frame */
3778         if(STACK_MODEL_LARGE)
3779           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3780         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3781
3782         if(STACK_MODEL_LARGE)
3783           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3784         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3785       }
3786     }
3787
3788     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3789           && sym->stack) {
3790
3791       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3792
3793       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3794       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3795       emitSKPC;
3796       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3797     }
3798           
3799     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3800       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3801         _G.useWreg = 0;
3802       else
3803         _G.useWreg = 1;
3804     } else
3805       _G.useWreg = 0;
3806
3807     /* if callee-save to be used for this function
3808      * then save the registers being used in this function */
3809 //    if (IFFUNC_CALLEESAVES(sym->type))
3810     if(strcmp(sym->name, "main")) {
3811       int i;
3812
3813         /* if any registers used */
3814         if (sym->regsUsed) {
3815                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3816
3817           if(!xinst) {
3818             /* save the registers used */
3819             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3820             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3821               if (bitVectBitValue(sym->regsUsed,i)) {
3822 #if 0
3823                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3824 #endif
3825                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3826                 _G.nRegsSaved++;
3827
3828                 if(!pic16_regWithIdx(i)->wasUsed) {
3829                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3830                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3831                   pic16_regWithIdx(i)->wasUsed = 1;
3832                 }
3833               }
3834             }
3835           } else {
3836             
3837             /* xinst */
3838             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3839             for(i=0;i<sym->regsUsed->size;i++) {
3840               if(bitVectBitValue(sym->regsUsed, i)) {
3841                 _G.nRegsSaved++;
3842               }
3843             }
3844                         
3845 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3846           }
3847
3848           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3849
3850         }
3851     }
3852         
3853     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3854 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3855 }
3856
3857 /*-----------------------------------------------------------------*/
3858 /* genEndFunction - generates epilogue for functions               */
3859 /*-----------------------------------------------------------------*/
3860 static void genEndFunction (iCode *ic)
3861 {
3862   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3863
3864     FENTRY;
3865
3866     if(IFFUNC_ISNAKED(sym->type)) {
3867       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3868       return;
3869     }
3870
3871     _G.stack_lat = 0;
3872
3873     /* add code for ISCRITICAL */
3874     if(IFFUNC_ISCRITICAL(sym->type)) {
3875       /* if critical function, turn on interrupts */
3876       
3877       /* TODO: add code here -- VR */
3878     }
3879     
3880 //    sym->regsUsed = _G.fregsUsed;
3881     
3882     /* now we need to restore the registers */
3883     /* if any registers used */
3884
3885     /* first restore registers that might be used for stack access */
3886     if(_G.sregsAllocSet) {
3887     regs *sr;
3888     
3889       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3890       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3891         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3892       }
3893     }
3894
3895     if (strcmp(sym->name, "main") && sym->regsUsed) {
3896       int i;
3897
3898         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3899         /* restore registers used */
3900         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3901         for ( i = sym->regsUsed->size; i >= 0; i--) {
3902           if (bitVectBitValue(sym->regsUsed,i)) {
3903             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3904             _G.nRegsSaved--;
3905           }
3906         }
3907         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3908     }
3909
3910       
3911
3912     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3913           && sym->stack) {
3914       if (sym->stack == 1) {
3915         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3916         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3917       } else {
3918         // we have to add more than one...
3919         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3920         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3921         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3922         emitSKPNC;
3923         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3924         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3925         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3926       }
3927     }
3928
3929     if(strcmp(sym->name, "main")) {
3930       if(0
3931         || !options.ommitFramePtr
3932 //        || sym->regsUsed
3933         || IFFUNC_ARGS(sym->type)
3934         || FUNC_HASSTACKPARM(sym->etype)
3935         ) {
3936         /* restore stack frame */
3937         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3938         if(STACK_MODEL_LARGE)
3939           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3940       }
3941     }
3942
3943     _G.useWreg = 0;
3944
3945     if (IFFUNC_ISISR(sym->type)) {
3946       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclatu ));
3947       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_pclath ));
3948       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3949       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3950       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3951       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3952
3953       if(!FUNC_ISSHADOWREGS(sym->type)) {
3954         /* do not restore interrupt vector for WREG,STATUS,BSR
3955          * for high priority interrupt, see genFunction */
3956         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3957         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3958         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3959       }
3960 //      _G.interruptvector = 0;         /* sanity check */
3961
3962
3963       /* if debug then send end of function */
3964 /*      if (options.debug && currFunc)  */
3965       if (currFunc) {
3966         debugFile->writeEndFunction (currFunc, ic, 1);
3967       }
3968         
3969       if(_G.usefastretfie)
3970         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3971       else
3972         pic16_emitpcodeNULLop(POC_RETFIE);
3973
3974       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3975       
3976       _G.usefastretfie = 0;
3977       return;
3978     }
3979
3980     if (IFFUNC_ISCRITICAL(sym->type)) {
3981       pic16_emitcode("setb","ea");
3982     }
3983
3984     /* if debug then send end of function */
3985     if (currFunc) {
3986       debugFile->writeEndFunction (currFunc, ic, 1);
3987     }
3988
3989     /* insert code to restore stack frame, if user enabled it
3990      * and function is not main() */
3991          
3992
3993     pic16_emitpcodeNULLop(POC_RETURN);
3994
3995     /* Mark the end of a function */
3996     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3997 }
3998
3999
4000 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
4001 {
4002   unsigned long lit=1;
4003   operand *op;
4004   
4005     op = IC_LEFT(ic);
4006   
4007     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
4008     if(AOP_TYPE(op) == AOP_LIT) {
4009       if(!IS_FLOAT(operandType( op ))) {
4010         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
4011       } else {
4012         union {
4013           unsigned long lit_int;
4014           float lit_float;
4015         } info;
4016         
4017         /* take care if literal is a float */
4018         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
4019         lit = info.lit_int;
4020       }
4021     }
4022
4023     if (AOP_TYPE(op) == AOP_LIT) {
4024       /* FIXME: broken for
4025        *   char __at(0x456) foo;
4026        *   return &foo;
4027        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4028       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4029     } else if (AOP_TYPE(op) == AOP_PCODE
4030                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4031       /* char *s= "aaa"; return s; */
4032       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4033        *      that the generic pointer is interpreted correctly
4034        *      as referring to __code space, but this is fragile! */
4035       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4036       /* XXX: should check that dest != WREG */
4037       pic16_emitpcode(POC_MOVWF, dest);
4038     } else {
4039       if(dest->type == PO_WREG && (offset == 0)) {
4040         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4041         return;
4042       }
4043       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4044     }
4045 }
4046
4047 /*-----------------------------------------------------------------*/
4048 /* genRet - generate code for return statement                     */
4049 /*-----------------------------------------------------------------*/
4050 static void genRet (iCode *ic)
4051 {
4052   int size;
4053   operand *left;
4054
4055     FENTRY;
4056         /* if we have no return value then
4057          * just generate the "ret" */
4058         
4059         if (!IC_LEFT(ic)) 
4060                 goto jumpret;       
4061     
4062         /* we have something to return then
4063          * move the return value into place */
4064         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4065         size = AOP_SIZE(IC_LEFT(ic));
4066
4067         if(size <= 4) {
4068           if(size>3)
4069             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4070           
4071           if(size>2)
4072             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4073
4074           if(size>1)
4075             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4076           
4077           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4078
4079         } else {
4080                 /* >32-bits, setup stack and FSR0 */
4081                 while (size--) {
4082 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4083 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4084
4085                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4086
4087 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4088                         GpsuedoStkPtr++;
4089                 }
4090                         
4091                 /* setup FSR0 */
4092                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4093                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4094
4095                 if(STACK_MODEL_LARGE) {
4096                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4097                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4098                 } else {
4099                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4100                 }
4101         }
4102                                 
4103 #if 0
4104         /* old code, left here for reference -- VR */    
4105         while (size--) {
4106           char *l ;
4107
4108                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4109                         /* #NOCHANGE */
4110                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4111                         pic16_emitpcomment("push %s",l);
4112                         pushed++;
4113                 } else {
4114                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4115                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4116                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4117                         
4118                         if (strcmp(fReturn[offset],l)) {
4119                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4120                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4121                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4122                                 } else {
4123                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4124                                 }
4125                                 
4126                                 if(size) {
4127                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4128                                 }
4129                                 offset++;
4130                         }
4131                 }
4132         }    
4133
4134         if (pushed) {
4135                 while(pushed) {
4136                         pushed--;
4137                         if (strcmp(fReturn[pushed],"a"))
4138                                 pic16_emitcode("pop",fReturn[pushed]);
4139                         else
4140                                 pic16_emitcode("pop","acc");
4141                 }
4142         }
4143 #endif
4144
4145
4146         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4147     
4148 jumpret:
4149         /* generate a jump to the return label
4150          * if the next is not the return statement */
4151         if (!(ic->next && ic->next->op == LABEL
4152                 && IC_LABEL(ic->next) == returnLabel)) {
4153         
4154                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4155                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4156         }
4157 }
4158
4159 /*-----------------------------------------------------------------*/
4160 /* genLabel - generates a label                                    */
4161 /*-----------------------------------------------------------------*/
4162 static void genLabel (iCode *ic)
4163 {
4164   FENTRY;
4165
4166   /* special case never generate */
4167   if (IC_LABEL(ic) == entryLabel)
4168     return ;
4169
4170   pic16_emitpLabel(IC_LABEL(ic)->key);
4171 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4172 }
4173
4174 /*-----------------------------------------------------------------*/
4175 /* genGoto - generates a goto                                      */
4176 /*-----------------------------------------------------------------*/
4177 //tsd
4178 static void genGoto (iCode *ic)
4179 {
4180   FENTRY;
4181   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4182 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4183 }
4184
4185
4186 /*-----------------------------------------------------------------*/
4187 /* genMultbits :- multiplication of bits                           */
4188 /*-----------------------------------------------------------------*/
4189 static void genMultbits (operand *left, 
4190                          operand *right, 
4191                          operand *result)
4192 {
4193   FENTRY;
4194
4195   if(!pic16_sameRegs(AOP(result),AOP(right)))
4196     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4197
4198   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4199   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4200   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4201
4202 }
4203
4204
4205 /*-----------------------------------------------------------------*/
4206 /* genMultOneByte : 8 bit multiplication & division                */
4207 /*-----------------------------------------------------------------*/
4208 static void genMultOneByte (operand *left,
4209                             operand *right,
4210                             operand *result)
4211 {
4212
4213   FENTRY;
4214   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4215   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4216
4217   /* (if two literals, the value is computed before) */
4218   /* if one literal, literal on the right */
4219   if (AOP_TYPE(left) == AOP_LIT){
4220     operand *t = right;
4221     right = left;
4222     left = t;
4223   }
4224
4225         /* size is already checked in genMult == 1 */
4226 //      size = AOP_SIZE(result);
4227
4228         if (AOP_TYPE(right) == AOP_LIT){
4229                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4230                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4231                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4232                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4233         } else {
4234                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4235                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4236                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4237                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4238         }
4239         
4240         pic16_genMult8X8_n (left, right,result);
4241 }
4242
4243 #if 0
4244 /*-----------------------------------------------------------------*/
4245 /* genMultOneWord : 16 bit multiplication                          */
4246 /*-----------------------------------------------------------------*/
4247 static void genMultOneWord (operand *left,
4248                             operand *right,
4249                             operand *result)
4250 {
4251   FENTRY;
4252   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4253   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4254
4255   /* (if two literals, the value is computed before)
4256    * if one literal, literal on the right */
4257   if (AOP_TYPE(left) == AOP_LIT){
4258     operand *t = right;
4259     right = left;
4260     left = t;
4261   }
4262
4263   /* size is checked already == 2 */
4264 //  size = AOP_SIZE(result);
4265
4266   if (AOP_TYPE(right) == AOP_LIT) {
4267     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4268       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4269       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4270       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4271   } else {
4272     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4273       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4274       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4275       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4276   }
4277         
4278   pic16_genMult16X16_16(left, right,result);
4279 }
4280 #endif
4281
4282 #if 0
4283 /*-----------------------------------------------------------------*/
4284 /* genMultOneLong : 32 bit multiplication                          */
4285 /*-----------------------------------------------------------------*/
4286 static void genMultOneLong (operand *left,
4287                             operand *right,
4288                             operand *result)
4289 {
4290   FENTRY;
4291   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4292   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4293
4294   /* (if two literals, the value is computed before)
4295    * if one literal, literal on the right */
4296   if (AOP_TYPE(left) == AOP_LIT){
4297     operand *t = right;
4298     right = left;
4299     left = t;
4300   }
4301
4302   /* size is checked already == 4 */
4303 //  size = AOP_SIZE(result);
4304
4305   if (AOP_TYPE(right) == AOP_LIT) {
4306     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4307         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4308         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4309         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4310   } else {
4311     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4312         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4313         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4314         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4315   }
4316         
4317   pic16_genMult32X32_32(left, right,result);
4318 }
4319 #endif
4320
4321
4322
4323 /*-----------------------------------------------------------------*/
4324 /* genMult - generates code for multiplication                     */
4325 /*-----------------------------------------------------------------*/
4326 static void genMult (iCode *ic)
4327 {
4328   operand *left = IC_LEFT(ic);
4329   operand *right = IC_RIGHT(ic);
4330   operand *result= IC_RESULT(ic);   
4331
4332     FENTRY;
4333         /* assign the amsops */
4334         pic16_aopOp (left,ic,FALSE);
4335         pic16_aopOp (right,ic,FALSE);
4336         pic16_aopOp (result,ic,TRUE);
4337
4338         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4339
4340         /* special cases first *
4341         * both are bits */
4342         if (AOP_TYPE(left) == AOP_CRY
4343                 && AOP_TYPE(right)== AOP_CRY) {
4344                 genMultbits(left,right,result);
4345           goto release ;
4346         }
4347
4348         /* if both are of size == 1 */
4349         if(AOP_SIZE(left) == 1
4350                 && AOP_SIZE(right) == 1) {
4351                 genMultOneByte(left,right,result);
4352           goto release ;
4353         }
4354
4355 #if 0
4356         /* if both are of size == 2 */
4357         if(AOP_SIZE(left) == 2
4358                 && AOP_SIZE(right) == 2) {
4359                 genMultOneWord(left, right, result);
4360           goto release;
4361         }
4362         
4363         /* if both are of size == 4 */
4364         if(AOP_SIZE(left) == 4
4365                 && AOP_SIZE(right) == 4) {
4366                 genMultOneLong(left, right, result);
4367           goto release;
4368         }
4369 #endif
4370
4371         fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
4372         assert( !"Multiplication should have been transformed into function call!" );
4373
4374         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4375
4376
4377         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4378         /* should have been converted to function call */
4379         assert(0) ;
4380
4381 release :
4382         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4383         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4384         pic16_freeAsmop(result,NULL,ic,TRUE); 
4385 }
4386
4387 #if 0
4388 /*-----------------------------------------------------------------*/
4389 /* genDivbits :- division of bits                                  */
4390 /*-----------------------------------------------------------------*/
4391 static void genDivbits (operand *left, 
4392                         operand *right, 
4393                         operand *result)
4394 {
4395   char *l;
4396
4397     FENTRY;
4398     /* the result must be bit */    
4399     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4400     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4401
4402     MOVA(l);    
4403
4404     pic16_emitcode("div","ab");
4405     pic16_emitcode("rrc","a");
4406     pic16_aopPut(AOP(result),"c",0);
4407 }
4408
4409 /*-----------------------------------------------------------------*/
4410 /* genDivOneByte : 8 bit division                                  */
4411 /*-----------------------------------------------------------------*/
4412 static void genDivOneByte (operand *left,
4413                            operand *right,
4414                            operand *result)
4415 {
4416   sym_link *opetype = operandType(result);
4417   char *l ;
4418   symbol *lbl ;
4419   int size,offset;
4420
4421         /* result = divident / divisor
4422          * - divident may be a register or a literal,
4423          * - divisor may be a register or a literal,
4424          * so there are 3 cases (literal / literal is optimized
4425          * by the front-end) to handle.
4426          * In addition we must handle signed and unsigned, which
4427          * result in 6 final different cases -- VR */
4428
4429     FENTRY;
4430     
4431     size = AOP_SIZE(result) - 1;
4432     offset = 1;
4433     /* signed or unsigned */
4434     if (SPEC_USIGN(opetype)) {
4435       pCodeOp *pct1,    /* count */
4436                 *pct2,  /* reste */
4437                 *pct3;  /* temp */
4438       symbol *label1, *label2, *label3;;
4439
4440
4441         /* unsigned is easy */
4442
4443         pct1 = pic16_popGetTempReg(1);
4444         pct2 = pic16_popGetTempReg(1);
4445         pct3 = pic16_popGetTempReg(1);
4446         
4447         label1 = newiTempLabel(NULL);
4448         label2 = newiTempLabel(NULL);
4449         label3 = newiTempLabel(NULL);
4450
4451         /* the following algorithm is extracted from divuint.c */
4452
4453         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4454         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4455         
4456         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4457
4458         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4459         
4460         pic16_emitpLabel(label1->key);
4461         
4462         emitCLRC;
4463         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4464
4465
4466         emitCLRC;
4467         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4468         
4469
4470         emitSKPNC;
4471         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4472         
4473         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4474         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4475         
4476         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4477         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4478         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4479         
4480         pic16_emitpLabel( label3->key );
4481         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4482         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4483         
4484         
4485
4486         pic16_emitpLabel(label2->key);
4487         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4488         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4489         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4490         
4491         /* result is in wreg */
4492         if(AOP_TYPE(result) != AOP_ACC)
4493                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4494
4495         pic16_popReleaseTempReg( pct3, 1);
4496         pic16_popReleaseTempReg( pct2, 1);
4497         pic16_popReleaseTempReg( pct1, 1);
4498
4499         return ;
4500     }
4501
4502     /* signed is a little bit more difficult */
4503
4504     /* save the signs of the operands */
4505     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4506     MOVA(l);    
4507     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4508     pic16_emitcode("push","acc"); /* save it on the stack */
4509
4510     /* now sign adjust for both left & right */
4511     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4512     MOVA(l);       
4513     lbl = newiTempLabel(NULL);
4514     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4515     pic16_emitcode("cpl","a");   
4516     pic16_emitcode("inc","a");
4517     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4518     pic16_emitcode("mov","b,a");
4519
4520     /* sign adjust left side */
4521     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4522     MOVA(l);
4523
4524     lbl = newiTempLabel(NULL);
4525     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4526     pic16_emitcode("cpl","a");
4527     pic16_emitcode("inc","a");
4528     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4529
4530     /* now the division */
4531     pic16_emitcode("div","ab");
4532     /* we are interested in the lower order
4533     only */
4534     pic16_emitcode("mov","b,a");
4535     lbl = newiTempLabel(NULL);
4536     pic16_emitcode("pop","acc");   
4537     /* if there was an over flow we don't 
4538     adjust the sign of the result */
4539     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4540     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4541     CLRC;
4542     pic16_emitcode("clr","a");
4543     pic16_emitcode("subb","a,b");
4544     pic16_emitcode("mov","b,a");
4545     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4546
4547     /* now we are done */
4548     pic16_aopPut(AOP(result),"b",0);
4549     if(size > 0){
4550         pic16_emitcode("mov","c,b.7");
4551         pic16_emitcode("subb","a,acc");   
4552     }
4553     while (size--)
4554         pic16_aopPut(AOP(result),"a",offset++);
4555
4556 }
4557 #endif
4558
4559 /*-----------------------------------------------------------------*/
4560 /* genDiv - generates code for division                            */
4561 /*-----------------------------------------------------------------*/
4562 static void genDiv (iCode *ic)
4563 {
4564     operand *left = IC_LEFT(ic);
4565     operand *right = IC_RIGHT(ic);
4566     operand *result= IC_RESULT(ic);   
4567     int negated = 0;
4568     int leftVal = 0, rightVal = 0;
4569     int signedLits = 0;
4570     char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
4571     int op = 0;
4572     
4573         /* Division is a very lengthy algorithm, so it is better
4574          * to call support routines than inlining algorithm.
4575          * Division functions written here just in case someone
4576          * wants to inline and not use the support libraries -- VR */
4577
4578     FENTRY;
4579     
4580     /* assign the amsops */
4581     pic16_aopOp (left,ic,FALSE);
4582     pic16_aopOp (right,ic,FALSE);
4583     pic16_aopOp (result,ic,TRUE);
4584
4585     if (ic->op == '/')
4586       op = 0;
4587     else if (ic->op == '%')
4588       op = 1;
4589     else
4590       assert( !"invalid operation requested in genDivMod" );
4591
4592     /* get literal values */
4593     if (IS_VALOP(left)) {
4594       leftVal = (int)floatFromVal( OP_VALUE(left) );
4595       assert( leftVal >= -128 && leftVal < 256 );
4596       if (leftVal < 0) { signedLits++; }
4597     }
4598     if (IS_VALOP(right)) {
4599       rightVal = (int)floatFromVal( OP_VALUE(right) );
4600       assert( rightVal >= -128 && rightVal < 256 );
4601       if (rightVal < 0) { signedLits++; }
4602     }
4603
4604     /* We should only come here to convert all
4605      * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
4606      * with exactly one operand being s8_t into
4607      * u8_t x u8_t -> u8_t. All other cases should have been
4608      * turned into calls to support routines beforehand... */
4609     if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
4610         && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
4611     {
4612       if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
4613           && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
4614       {
4615         /* Both operands are signed or negative, use _divschar
4616          * instead of _divuchar */
4617         pushaop(AOP(right), 0);
4618         pushaop(AOP(left), 0);
4619
4620         /* call _divschar */
4621         pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
4622
4623         {
4624           symbol *sym;
4625           sym = newSymbol( functions[op][0], 0 );
4626           sym->used++;
4627           strcpy(sym->rname, functions[op][0]);
4628           checkAddSym(&externs, sym);
4629         }
4630
4631         /* assign result */
4632         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4633         if (AOP_SIZE(result) > 1)
4634         {
4635           pic16_emitpcode(POC_MOVFF,
4636               pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
4637                 pic16_popGet(AOP(result), 1)));
4638           /* sign extend */
4639           pic16_addSign(result, 2, 1);
4640         }
4641
4642         /* clean up stack */
4643         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4644         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4645
4646         goto release;
4647       }
4648       
4649       /* push right operand */
4650       if (IS_VALOP(right)) {
4651         if (rightVal < 0) {
4652           pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
4653           negated++;
4654         } else {
4655           pushaop(AOP(right), 0);
4656         }
4657       } else if (!IS_UNSIGNED(operandType(right))) {
4658         pic16_mov2w(AOP(right), 0);
4659         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4660         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4661         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4662         negated++;
4663       } else {
4664         pushaop(AOP(right), 0);
4665       }
4666
4667       /* push left operand */
4668       if (IS_VALOP(left)) {
4669         if (leftVal < 0) {
4670           pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
4671           negated++;
4672         } else {
4673           pushaop(AOP(left), 0);
4674         }
4675       } else if (!IS_UNSIGNED(operandType(left))) {
4676         pic16_mov2w(AOP(left),0);
4677         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4678         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4679         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
4680         negated++;
4681       } else {
4682         pushaop(AOP(left), 0);
4683       }
4684       
4685       /* call _divuchar */
4686       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
4687
4688       {
4689         symbol *sym;
4690         sym = newSymbol( functions[op][1], 0 );
4691         sym->used++;
4692         strcpy(sym->rname, functions[op][1]);
4693         checkAddSym(&externs, sym);
4694       }
4695
4696       /* Revert negation(s) from above.
4697        * This is inefficient: if both operands are negative, this
4698        * should not touch WREG. However, determining that exactly
4699        * one operand was negated costs at least 3 instructions,
4700        * so there is nothing to be gained here, is there?
4701        *
4702        * I negate WREG because either operand might share registers with
4703        * result, so assigning first might destroy an operand. */
4704       
4705       /* For the modulus operator, (a/b)*b == a shall hold.
4706        * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
4707        *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
4708        *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
4709        *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
4710        * Only invert the result if the left operand is negative (sigh).
4711        */
4712       if (AOP_SIZE(result) <= 1 || !negated)
4713       {
4714         if (ic->op == '/')
4715         {
4716           if (IS_VALOP(right)) {
4717             if (rightVal < 0) {
4718               /* we negated this operand above */
4719               pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4720             }
4721           } else if (!IS_UNSIGNED(operandType(right))) {
4722             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4723             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4724           }
4725         }
4726
4727         if (IS_VALOP(left)) {
4728           if (leftVal < 0) {
4729             /* we negated this operand above */
4730             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4731           }
4732         } else if (!IS_UNSIGNED(operandType(left))) {
4733           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4734           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
4735         }
4736
4737         /* Move result to destination. */
4738         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4739
4740         /* Zero-extend:  no operand was signed (or result is just a byte). */
4741         pic16_addSign(result, 1, 0);
4742       } else {
4743         assert( AOP_SIZE(result) > 1 );
4744         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
4745         if (ic->op == '/')
4746         {
4747           if (IS_VALOP(right)) {
4748             if (rightVal < 0) {
4749               /* we negated this operand above */
4750               pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4751             }
4752           } else if (!IS_UNSIGNED(operandType(right))) {
4753             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
4754             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4755           }
4756         }
4757
4758         if (IS_VALOP(left)) {
4759           if (leftVal < 0) {
4760             /* we negated this operand above */
4761             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4762           }
4763         } else if (!IS_UNSIGNED(operandType(left))) {
4764           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
4765           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
4766         }
4767
4768         /* Move result to destination. */
4769         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4770
4771         /* Negate result if required. */
4772         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
4773         pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
4774
4775         /* Sign-extend. */
4776         pic16_addSign(result, 2, 1);
4777       }
4778
4779       /* clean up stack */
4780       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4781       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
4782       goto release;
4783     }
4784
4785 #if 0
4786     /* special cases first */
4787     /* both are bits */
4788     if (AOP_TYPE(left) == AOP_CRY &&
4789         AOP_TYPE(right)== AOP_CRY) {
4790         genDivbits(left,right,result);
4791         goto release ;
4792     }
4793
4794     /* if both are of size == 1 */
4795     if (AOP_SIZE(left) == 1 &&
4796         AOP_SIZE(right) == 1 ) {
4797         genDivOneByte(left,right,result);
4798         goto release ;
4799     }
4800 #endif
4801
4802     /* should have been converted to function call */
4803     assert(0);
4804 release :
4805     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4806     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4807     pic16_freeAsmop(result,NULL,ic,TRUE); 
4808 }
4809
4810 #if 0
4811 /*-----------------------------------------------------------------*/
4812 /* genModbits :- modulus of bits                                   */
4813 /*-----------------------------------------------------------------*/
4814 static void genModbits (operand *left, 
4815                         operand *right, 
4816                         operand *result)
4817 {
4818   char *l;
4819
4820     FENTRY;  
4821     
4822     werror(W_POSSBUG2, __FILE__, __LINE__);
4823     /* the result must be bit */    
4824     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4825     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4826
4827     MOVA(l);       
4828
4829     pic16_emitcode("div","ab");
4830     pic16_emitcode("mov","a,b");
4831     pic16_emitcode("rrc","a");
4832     pic16_aopPut(AOP(result),"c",0);
4833 }
4834
4835 /*-----------------------------------------------------------------*/
4836 /* genModOneByte : 8 bit modulus                                   */
4837 /*-----------------------------------------------------------------*/
4838 static void genModOneByte (operand *left,
4839                            operand *right,
4840                            operand *result)
4841 {
4842   sym_link *opetype = operandType(result);
4843   char *l ;
4844   symbol *lbl ;
4845
4846     FENTRY;
4847     werror(W_POSSBUG2, __FILE__, __LINE__);
4848
4849     /* signed or unsigned */
4850     if (SPEC_USIGN(opetype)) {
4851         /* unsigned is easy */
4852         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4853         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4854         MOVA(l);    
4855         pic16_emitcode("div","ab");
4856         pic16_aopPut(AOP(result),"b",0);
4857         return ;
4858     }
4859
4860     /* signed is a little bit more difficult */
4861
4862     /* save the signs of the operands */
4863     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4864     MOVA(l);
4865
4866     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4867     pic16_emitcode("push","acc"); /* save it on the stack */
4868
4869     /* now sign adjust for both left & right */
4870     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4871     MOVA(l);
4872
4873     lbl = newiTempLabel(NULL);
4874     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4875     pic16_emitcode("cpl","a");   
4876     pic16_emitcode("inc","a");
4877     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4878     pic16_emitcode("mov","b,a"); 
4879
4880     /* sign adjust left side */
4881     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4882     MOVA(l);
4883
4884     lbl = newiTempLabel(NULL);
4885     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4886     pic16_emitcode("cpl","a");   
4887     pic16_emitcode("inc","a");
4888     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4889
4890     /* now the multiplication */
4891     pic16_emitcode("div","ab");
4892     /* we are interested in the lower order
4893     only */
4894     lbl = newiTempLabel(NULL);
4895     pic16_emitcode("pop","acc");   
4896     /* if there was an over flow we don't 
4897     adjust the sign of the result */
4898     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4899     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4900     CLRC ;
4901     pic16_emitcode("clr","a");
4902     pic16_emitcode("subb","a,b");
4903     pic16_emitcode("mov","b,a");
4904     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4905
4906     /* now we are done */
4907     pic16_aopPut(AOP(result),"b",0);
4908
4909 }
4910 #endif
4911
4912 /*-----------------------------------------------------------------*/
4913 /* genMod - generates code for division                            */
4914 /*-----------------------------------------------------------------*/
4915 static void genMod (iCode *ic)
4916 {
4917   /* Task deferred to genDiv */
4918   genDiv(ic);
4919 #if 0
4920   operand *left = IC_LEFT(ic);
4921   operand *right = IC_RIGHT(ic);
4922   operand *result= IC_RESULT(ic);  
4923
4924     FENTRY;
4925     
4926     /* assign the amsops */
4927     pic16_aopOp (left,ic,FALSE);
4928     pic16_aopOp (right,ic,FALSE);
4929     pic16_aopOp (result,ic,TRUE);
4930
4931     /* special cases first */
4932     /* both are bits */
4933     if (AOP_TYPE(left) == AOP_CRY &&
4934         AOP_TYPE(right)== AOP_CRY) {
4935         genModbits(left,right,result);
4936         goto release ;
4937     }
4938
4939     /* if both are of size == 1 */
4940     if (AOP_SIZE(left) == 1 &&
4941         AOP_SIZE(right) == 1 ) {
4942         genModOneByte(left,right,result);
4943         goto release ;
4944     }
4945
4946     /* should have been converted to function call */
4947     assert(0);
4948
4949 release :
4950     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4951     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4952     pic16_freeAsmop(result,NULL,ic,TRUE); 
4953 #endif
4954 }
4955
4956 /*-----------------------------------------------------------------*/
4957 /* genIfxJump :- will create a jump depending on the ifx           */
4958 /*-----------------------------------------------------------------*/
4959 /*
4960   note: May need to add parameter to indicate when a variable is in bit space.
4961 */
4962 static void genIfxJump (iCode *ic, char *jval)
4963 {
4964   FENTRY;
4965   
4966     /* if true label then we jump if condition
4967     supplied is true */
4968     if ( IC_TRUE(ic) ) {
4969
4970         if(strcmp(jval,"a") == 0)
4971           emitSKPZ;
4972         else if (strcmp(jval,"c") == 0)
4973           emitSKPNC;
4974         else {
4975           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4976           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4977         }
4978
4979         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4980         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4981
4982     }
4983     else {
4984         /* false label is present */
4985         if(strcmp(jval,"a") == 0)
4986           emitSKPNZ;
4987         else if (strcmp(jval,"c") == 0)
4988           emitSKPC;
4989         else {
4990           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4991           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4992         }
4993
4994         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4995         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4996
4997     }
4998
4999
5000     /* mark the icode as generated */
5001     ic->generated = 1;
5002 }
5003
5004 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
5005 {
5006   FENTRY;
5007   
5008     /* if true label then we jump if condition
5009     supplied is true */
5010     if ( IC_TRUE(ic) ) {
5011       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
5012       pic16_emitpcode(POC_BTFSC, jop);
5013
5014       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5015       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
5016
5017     } else {
5018       /* false label is present */
5019       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
5020       pic16_emitpcode(POC_BTFSS, jop);
5021           
5022       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5023       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
5024     }
5025
5026
5027     /* mark the icode as generated */
5028     ic->generated = 1;
5029 }
5030
5031 #if 0
5032 // not needed ATM
5033
5034 /*-----------------------------------------------------------------*/
5035 /* genSkip                                                         */
5036 /*-----------------------------------------------------------------*/
5037 static void genSkip(iCode *ifx,int status_bit)
5038 {
5039   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5040   if(!ifx)
5041     return;
5042
5043   if ( IC_TRUE(ifx) ) {
5044     switch(status_bit) {
5045     case 'z':
5046       emitSKPNZ;
5047       break;
5048
5049     case 'c':
5050       emitSKPNC;
5051       break;
5052
5053     case 'd':
5054       emitSKPDC;
5055       break;
5056
5057     }
5058
5059     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5060     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5061
5062   } else {
5063
5064     switch(status_bit) {
5065
5066     case 'z':
5067       emitSKPZ;
5068       break;
5069
5070     case 'c':
5071       emitSKPC;
5072       break;
5073
5074     case 'd':
5075       emitSKPDC;
5076       break;
5077     }
5078     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5079     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5080
5081   }
5082
5083 }
5084 #endif
5085
5086 /*-----------------------------------------------------------------*/
5087 /* genSkipc                                                        */
5088 /*-----------------------------------------------------------------*/
5089 static void genSkipc(resolvedIfx *rifx)
5090 {
5091   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5092   
5093   if(!rifx)
5094     return;
5095
5096   if(rifx->condition)
5097     emitSKPNC;
5098   else
5099     emitSKPC;
5100
5101   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
5102   rifx->generated = 1;
5103 }
5104
5105 #if !(USE_SIMPLE_GENCMP)
5106 /*-----------------------------------------------------------------*/
5107 /* genSkipz2                                                       */
5108 /*-----------------------------------------------------------------*/
5109 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
5110 {
5111   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
5112   
5113   if(!rifx)
5114     return;
5115
5116   if( (rifx->condition ^ invert_condition) & 1)
5117     emitSKPZ;
5118   else
5119     emitSKPNZ;
5120
5121   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5122   rifx->generated = 1;
5123 }
5124 #endif
5125
5126 #if 0
5127 /*-----------------------------------------------------------------*/
5128 /* genSkipz                                                        */
5129 /*-----------------------------------------------------------------*/
5130 static void genSkipz(iCode *ifx, int condition)
5131 {
5132   if(!ifx)
5133     return;
5134
5135   if(condition)
5136     emitSKPNZ;
5137   else
5138     emitSKPZ;
5139
5140   if ( IC_TRUE(ifx) )
5141     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5142   else
5143     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5144
5145   if ( IC_TRUE(ifx) )
5146     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
5147   else
5148     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
5149
5150 }
5151 #endif
5152
5153 #if !(USE_SIMPLE_GENCMP)
5154 /*-----------------------------------------------------------------*/
5155 /* genSkipCond                                                     */
5156 /*-----------------------------------------------------------------*/
5157 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
5158 {
5159   if(!rifx)
5160     return;
5161
5162   if(rifx->condition)
5163     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5164   else
5165     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
5166
5167
5168   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
5169   rifx->generated = 1;
5170 }
5171 #endif
5172
5173 #if 0
5174 /*-----------------------------------------------------------------*/
5175 /* genChkZeroes :- greater or less than comparison                 */
5176 /*     For each byte in a literal that is zero, inclusive or the   */
5177 /*     the corresponding byte in the operand with W                */
5178 /*     returns true if any of the bytes are zero                   */
5179 /*-----------------------------------------------------------------*/
5180 static int genChkZeroes(operand *op, int lit,  int size)
5181 {
5182
5183   int i;
5184   int flag =1;
5185
5186   while(size--) {
5187     i = (lit >> (size*8)) & 0xff;
5188
5189     if(i==0) {
5190       if(flag) 
5191         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
5192       else
5193         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
5194       flag = 0;
5195     }
5196   }
5197
5198   return (flag==0);
5199 }
5200 #endif
5201
5202
5203 /*-----------------------------------------------------------------*/
5204 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
5205 /*                  aop (if it's NOT a literal) or from lit (if    */
5206 /*                  aop is a literal)                              */
5207 /*-----------------------------------------------------------------*/
5208 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
5209   if (aop->type == AOP_LIT) {
5210     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
5211   } else {
5212     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
5213   }
5214 }
5215
5216 /*-----------------------------------------------------------------*/
5217 /* genCmp :- greater or less than comparison                       */
5218 /*-----------------------------------------------------------------*/
5219
5220 #if USE_SIMPLE_GENCMP           /* { */
5221
5222 /* genCmp performs a left < right comparison, stores
5223  * the outcome in result (if != NULL) and generates
5224  * control flow code for the ifx (if != NULL).
5225  *
5226  * This version leaves in sequences like
5227  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
5228  * which should be optmized by the peephole
5229  * optimizer - RN 2005-01-01 */
5230 static void genCmp (operand *left,operand *right,
5231                     operand *result, iCode *ifx, int sign)
5232 {
5233   resolvedIfx rIfx;
5234   int size;
5235   int offs;
5236   symbol *templbl;
5237   operand *dummy;
5238   unsigned long lit;
5239   unsigned long mask;
5240   int performedLt;
5241
5242   FENTRY;
5243   
5244   assert (left && right);
5245   assert (AOP_SIZE(left) == AOP_SIZE(right));
5246
5247   size = AOP_SIZE(right) - 1;
5248   mask = (0x100UL << (size*8)) - 1;
5249   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5250   performedLt = 1;
5251   templbl = NULL;
5252   lit = 0;
5253   
5254   resolveIfx (&rIfx, ifx);
5255
5256   /* handle for special cases */
5257   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5258       return;
5259
5260   /**********************************************************************
5261    * handle bits - bit compares are promoted to int compares seemingly! *
5262    **********************************************************************/
5263 #if 0
5264   // THIS IS COMPLETELY UNTESTED!
5265   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5266     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5267     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5268     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5269
5270     emitSETC;
5271     // 1 < {0,1} is false --> clear C by skipping the next instruction
5272     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5273     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5274     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5275     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5276     emitCLRC; // only skipped for left=0 && right=1
5277
5278     goto correct_result_in_carry;
5279   } // if
5280 #endif
5281
5282   /*************************************************
5283    * make sure that left is register (or the like) *
5284    *************************************************/
5285   if (!isAOP_REGlike(left)) {
5286     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5287     assert (isAOP_LIT(left));
5288     assert (isAOP_REGlike(right));
5289     // swap left and right
5290     // left < right <==> right > left <==> (right >= left + 1)
5291     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5292
5293     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5294       // MAXVALUE < right? always false
5295       if (performedLt) emitCLRC; else emitSETC;
5296       goto correct_result_in_carry;
5297     } // if
5298
5299     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5300     // that's why we handled it above.
5301     lit++;
5302
5303     dummy = left;
5304     left = right;
5305     right = dummy;
5306
5307     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5308   } else if (isAOP_LIT(right)) {
5309     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5310   } // if
5311
5312   assert (isAOP_REGlike(left)); // left must be register or the like
5313   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5314
5315   /*************************************************
5316    * special cases go here                         *
5317    *************************************************/
5318
5319   if (isAOP_LIT(right)) {
5320     if (!sign) {
5321       // unsigned comparison to a literal
5322       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5323       if (lit == 0) {
5324         // unsigned left < 0? always false
5325         if (performedLt) emitCLRC; else emitSETC;
5326         goto correct_result_in_carry;
5327       }
5328     } else {
5329       // signed comparison to a literal
5330       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5331       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5332         // signed left < 0x80000000? always false
5333         if (performedLt) emitCLRC; else emitSETC;
5334         goto correct_result_in_carry;
5335       } else if (lit == 0) {
5336         // compare left < 0; set CARRY if SIGNBIT(left) is set
5337         if (performedLt) emitSETC; else emitCLRC;
5338         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5339         if (performedLt) emitCLRC; else emitSETC;
5340         goto correct_result_in_carry;
5341       }
5342     } // if (!sign)
5343   } // right is literal
5344
5345   /*************************************************
5346    * perform a general case comparison             *
5347    * make sure we get CARRY==1 <==> left >= right  *
5348    *************************************************/
5349   // compare most significant bytes
5350   //DEBUGpc ("comparing bytes at offset %d", size);
5351   if (!sign) {
5352     // unsigned comparison
5353     mov2w_regOrLit (AOP(right), lit, size);
5354     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5355   } else {
5356     // signed comparison
5357     // (add 2^n to both operands then perform an unsigned comparison)
5358     if (isAOP_LIT(right)) {
5359       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5360       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5361
5362       if (litbyte == 0x80) {
5363         // left >= 0x80 -- always true, but more bytes to come
5364         pic16_mov2w (AOP(left), size);
5365         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5366         emitSETC;
5367       } else {
5368         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5369         pic16_mov2w (AOP(left), size);
5370         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5371         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5372       } // if
5373     } else {
5374       /* using PRODL as a temporary register here */
5375       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5376       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5377       pic16_mov2w (AOP(left), size);
5378       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5379       pic16_emitpcode (POC_MOVWF, pctemp);
5380       pic16_mov2w (AOP(right), size);
5381       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5382       pic16_emitpcode (POC_SUBFW, pctemp);
5383       //pic16_popReleaseTempReg(pctemp, 1);
5384     }
5385   } // if (!sign)
5386
5387   // compare remaining bytes (treat as unsigned case from above)
5388   templbl = newiTempLabel ( NULL );
5389   offs = size;
5390   while (offs--) {
5391     //DEBUGpc ("comparing bytes at offset %d", offs);
5392     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5393     mov2w_regOrLit (AOP(right), lit, offs);
5394     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5395   } // while (offs)
5396   pic16_emitpLabel (templbl->key);
5397   goto result_in_carry;
5398
5399 result_in_carry:
5400   
5401   /****************************************************
5402    * now CARRY contains the result of the comparison: *
5403    * SUBWF sets CARRY iff                             *
5404    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5405    * (F=left, W=right)                                *
5406    ****************************************************/
5407
5408   if (performedLt) {
5409     if (result && AOP_TYPE(result) != AOP_CRY) {
5410       // value will be stored
5411       emitTOGC;
5412     } else {
5413       // value wil only be used in the following genSkipc()
5414       rIfx.condition ^= 1;
5415     }
5416   } // if
5417
5418 correct_result_in_carry:
5419
5420   // assign result to variable (if neccessary)
5421   if (result && AOP_TYPE(result) != AOP_CRY) {
5422     //DEBUGpc ("assign result");
5423     size = AOP_SIZE(result);
5424     while (size--) {
5425       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5426     } // while
5427     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5428   } // if (result)
5429
5430   // perform conditional jump
5431   if (ifx) {
5432     //DEBUGpc ("generate control flow");
5433     genSkipc (&rIfx);
5434     ifx->generated = 1;
5435   } // if
5436 }
5437
5438 #elif 1         /* } */
5439                 /* { */
5440       /* original code */
5441 static void genCmp (operand *left,operand *right,
5442                     operand *result, iCode *ifx, int sign)
5443 {
5444   int size; //, offset = 0 ;
5445   unsigned long lit = 0L,i = 0;
5446   resolvedIfx rFalseIfx;
5447   //  resolvedIfx rTrueIfx;
5448   symbol *truelbl;
5449   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5450 /*
5451   if(ifx) {
5452     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5453     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5454   }
5455 */
5456
5457   FENTRY;
5458   
5459   resolveIfx(&rFalseIfx,ifx);
5460   truelbl  = newiTempLabel(NULL);
5461   size = max(AOP_SIZE(left),AOP_SIZE(right));
5462
5463   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5464
5465 #define _swapp
5466
5467   /* if literal is on the right then swap with left */
5468   if ((AOP_TYPE(right) == AOP_LIT)) {
5469     operand *tmp = right ;
5470     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5471     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5472 #ifdef _swapp
5473
5474     lit = (lit - 1) & mask;
5475     right = left;
5476     left = tmp;
5477     rFalseIfx.condition ^= 1;
5478 #endif
5479
5480   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5481     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5482   }
5483
5484
5485   //if(IC_TRUE(ifx) == NULL)
5486   /* if left & right are bit variables */
5487   if (AOP_TYPE(left) == AOP_CRY &&
5488       AOP_TYPE(right) == AOP_CRY ) {
5489     assert (0 && "bit variables used in genCmp");
5490     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5491     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5492   } else {
5493     /* subtract right from left if at the
5494        end the carry flag is set then we know that
5495        left is greater than right */
5496
5497     symbol *lbl  = newiTempLabel(NULL);
5498
5499 #if 0
5500         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5501                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5502 #endif
5503
5504 #ifndef _swapp
5505     if(AOP_TYPE(right) == AOP_LIT) {
5506
5507       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5508
5509       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5510
5511       /* special cases */
5512
5513       if(lit == 0) {
5514
5515         if(sign != 0) 
5516           genSkipCond(&rFalseIfx,left,size-1,7);
5517         else 
5518           /* no need to compare to 0...*/
5519           /* NOTE: this is a de-generate compare that most certainly 
5520            *       creates some dead code. */
5521           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5522
5523         if(ifx) ifx->generated = 1;
5524         return;
5525
5526       }
5527       size--;
5528
5529       if(size == 0) {
5530         //i = (lit >> (size*8)) & 0xff;
5531         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5532         
5533         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5534
5535         i = ((0-lit) & 0xff);
5536         if(sign) {
5537           if( i == 0x81) { 
5538             /* lit is 0x7f, all signed chars are less than
5539              * this except for 0x7f itself */
5540             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5541             genSkipz2(&rFalseIfx,0);
5542           } else {
5543             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5544             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5545             genSkipc(&rFalseIfx);
5546           }
5547
5548         } else {
5549           if(lit == 1) {
5550             genSkipz2(&rFalseIfx,1);
5551           } else {
5552             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5553             genSkipc(&rFalseIfx);
5554           }
5555         }
5556
5557         if(ifx) ifx->generated = 1;
5558         return;
5559       }
5560
5561       /* chars are out of the way. now do ints and longs */
5562
5563
5564       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5565         
5566       /* special cases */
5567
5568       if(sign) {
5569
5570         if(lit == 0) {
5571           genSkipCond(&rFalseIfx,left,size,7);
5572           if(ifx) ifx->generated = 1;
5573           return;
5574         }
5575
5576         if(lit <0x100) {
5577           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5578
5579           //rFalseIfx.condition ^= 1;
5580           //genSkipCond(&rFalseIfx,left,size,7);
5581           //rFalseIfx.condition ^= 1;
5582
5583           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5584           if(rFalseIfx.condition)
5585             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5586           else
5587             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5588
5589           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5590           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5591           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5592
5593           while(size > 1)
5594             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5595
5596           if(rFalseIfx.condition) {
5597             emitSKPZ;
5598             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5599
5600           } else {
5601             emitSKPNZ;
5602           }
5603
5604           genSkipc(&rFalseIfx);
5605           pic16_emitpLabel(truelbl->key);
5606           if(ifx) ifx->generated = 1;
5607           return;
5608
5609         }
5610
5611         if(size == 1) {
5612
5613           if( (lit & 0xff) == 0) {
5614             /* lower byte is zero */
5615             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5616             i = ((lit >> 8) & 0xff) ^0x80;
5617             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5618             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5619             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5620             genSkipc(&rFalseIfx);
5621
5622
5623             if(ifx) ifx->generated = 1;
5624             return;
5625
5626           }
5627         } else {
5628           /* Special cases for signed longs */
5629           if( (lit & 0xffffff) == 0) {
5630             /* lower byte is zero */
5631             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5632             i = ((lit >> 8*3) & 0xff) ^0x80;
5633             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5634             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5635             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5636             genSkipc(&rFalseIfx);
5637
5638
5639             if(ifx) ifx->generated = 1;
5640             return;
5641
5642           }
5643
5644         }
5645
5646
5647         if(lit & (0x80 << (size*8))) {
5648           /* lit is negative */
5649           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5650
5651           //genSkipCond(&rFalseIfx,left,size,7);
5652
5653           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5654
5655           if(rFalseIfx.condition)
5656             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5657           else
5658             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5659
5660
5661         } else {
5662           /* lit is positive */
5663           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5664           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5665           if(rFalseIfx.condition)
5666             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5667           else
5668             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5669
5670         }
5671
5672         /*
5673           This works, but is only good for ints.
5674           It also requires a "known zero" register.
5675           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5676           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5677           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5678           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5679           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5680           genSkipc(&rFalseIfx);
5681
5682           pic16_emitpLabel(truelbl->key);
5683           if(ifx) ifx->generated = 1;
5684           return;
5685         **/
5686           
5687         /* There are no more special cases, so perform a general compare */
5688   
5689         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5690         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5691
5692         while(size--) {
5693
5694           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5695           emitSKPNZ;
5696           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5697         }
5698         //rFalseIfx.condition ^= 1;
5699         genSkipc(&rFalseIfx);
5700
5701         pic16_emitpLabel(truelbl->key);
5702
5703         if(ifx) ifx->generated = 1;
5704         return;
5705
5706
5707       }
5708
5709
5710       /* sign is out of the way. So now do an unsigned compare */
5711       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5712
5713
5714       /* General case - compare to an unsigned literal on the right.*/
5715
5716       i = (lit >> (size*8)) & 0xff;
5717       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5718       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5719       while(size--) {
5720         i = (lit >> (size*8)) & 0xff;
5721
5722         if(i) {
5723           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5724           emitSKPNZ;
5725           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5726         } else {
5727           /* this byte of the lit is zero, 
5728            *if it's not the last then OR in the variable */
5729           if(size)
5730             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5731         }
5732       }
5733
5734
5735       pic16_emitpLabel(lbl->key);
5736 //      pic16_emitpLabel(truelbl->key);
5737       //if(emitFinalCheck)
5738       genSkipc(&rFalseIfx);
5739       if(sign)
5740         pic16_emitpLabel(truelbl->key);
5741
5742       if(ifx) ifx->generated = 1;
5743       return;
5744
5745
5746     }
5747 #endif  // _swapp
5748
5749     if(AOP_TYPE(left) == AOP_LIT) {
5750       //symbol *lbl = newiTempLabel(NULL);
5751
5752       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5753
5754
5755       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5756
5757       /* Special cases */
5758       if((lit == 0) && (sign == 0)){
5759
5760         size--;
5761         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5762         while(size) 
5763           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5764
5765         genSkipz2(&rFalseIfx,0);
5766         if(ifx) ifx->generated = 1;
5767         return;
5768       }
5769
5770       if(size==1) {
5771         /* Special cases */
5772         lit &= 0xff;
5773         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5774           /* degenerate compare can never be true */
5775           if(rFalseIfx.condition == 0)
5776             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5777
5778           if(ifx) ifx->generated = 1;
5779           return;
5780         }
5781
5782         if(sign) {
5783           /* signed comparisons to a literal byte */
5784
5785           int lp1 = (lit+1) & 0xff;
5786
5787           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5788           switch (lp1) {
5789           case 0:
5790             rFalseIfx.condition ^= 1;
5791             genSkipCond(&rFalseIfx,right,0,7);
5792             break;
5793           case 0x7f:
5794             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5795             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5796             genSkipz2(&rFalseIfx,1);
5797             break;
5798           default:
5799             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5800             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5801             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5802             rFalseIfx.condition ^= 1;
5803             genSkipc(&rFalseIfx);
5804             break;
5805           }
5806         } else {
5807           /* unsigned comparisons to a literal byte */
5808
5809           switch(lit & 0xff ) {
5810           case 0:
5811             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5812             genSkipz2(&rFalseIfx,0);
5813             break;
5814           case 0x7f:
5815             rFalseIfx.condition ^= 1;
5816             genSkipCond(&rFalseIfx,right,0,7);
5817             break;
5818
5819           default:
5820             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5821             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5822             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5823             rFalseIfx.condition ^= 1;
5824             if (AOP_TYPE(result) == AOP_CRY)
5825               genSkipc(&rFalseIfx);
5826             else {
5827               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5828               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5829             }         
5830             break;
5831           }
5832         }
5833
5834         if(ifx) ifx->generated = 1;
5835         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5836                 goto check_carry;
5837         return;
5838
5839       } else {
5840
5841         /* Size is greater than 1 */
5842
5843         if(sign) {
5844           int lp1 = lit+1;
5845
5846           size--;
5847
5848           if(lp1 == 0) {
5849             /* this means lit = 0xffffffff, or -1 */
5850
5851
5852             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5853             rFalseIfx.condition ^= 1;
5854             genSkipCond(&rFalseIfx,right,size,7);
5855             if(ifx) ifx->generated = 1;
5856
5857             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5858               goto check_carry;
5859
5860             return;
5861           }
5862
5863           if(lit == 0) {
5864             int s = size;
5865
5866             if(rFalseIfx.condition) {
5867               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5868               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5869             }
5870
5871             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5872             while(size--)
5873               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5874
5875
5876             emitSKPZ;
5877             if(rFalseIfx.condition) {
5878               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5879               pic16_emitpLabel(truelbl->key);
5880             }else {
5881               rFalseIfx.condition ^= 1;
5882               genSkipCond(&rFalseIfx,right,s,7);
5883             }
5884
5885             if(ifx) ifx->generated = 1;
5886
5887             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5888               goto check_carry;
5889
5890             return;
5891           }
5892
5893           if((size == 1) &&  (0 == (lp1&0xff))) {
5894             /* lower byte of signed word is zero */
5895             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5896             i = ((lp1 >> 8) & 0xff) ^0x80;
5897             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5898             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5899             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5900
5901             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5902               emitTOGC;
5903               if(ifx) ifx->generated = 1;
5904               goto check_carry;
5905             } else {
5906               rFalseIfx.condition ^= 1;
5907               genSkipc(&rFalseIfx);
5908               if(ifx) ifx->generated = 1;
5909             }
5910
5911             return;
5912           }
5913
5914           if(lit & (0x80 << (size*8))) {
5915             /* Lit is less than zero */
5916             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5917             //rFalseIfx.condition ^= 1;
5918             //genSkipCond(&rFalseIfx,left,size,7);
5919             //rFalseIfx.condition ^= 1;
5920             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5921             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5922
5923             if(rFalseIfx.condition)
5924               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5925             else
5926               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5927
5928
5929           } else {
5930             /* Lit is greater than or equal to zero */
5931             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5932             //rFalseIfx.condition ^= 1;
5933             //genSkipCond(&rFalseIfx,right,size,7);
5934             //rFalseIfx.condition ^= 1;
5935
5936             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5937             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5938
5939             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5940             if(rFalseIfx.condition)
5941               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5942             else
5943               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5944
5945           }
5946
5947           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5948           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5949
5950           while(size--) {
5951
5952             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5953             emitSKPNZ;
5954             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5955           }
5956           rFalseIfx.condition ^= 1;
5957           //rFalseIfx.condition = 1;
5958           genSkipc(&rFalseIfx);
5959
5960           pic16_emitpLabel(truelbl->key);
5961
5962           if(ifx) ifx->generated = 1;
5963
5964
5965           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5966             goto check_carry;
5967
5968           return;
5969           // end of if (sign)
5970         } else {
5971
5972           /* compare word or long to an unsigned literal on the right.*/
5973
5974
5975           size--;
5976           if(lit < 0xff) {
5977             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5978             switch (lit) {
5979             case 0:
5980               break; /* handled above */
5981 /*
5982             case 0xff:
5983               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5984               while(size--)
5985                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5986               genSkipz2(&rFalseIfx,0);
5987               break;
5988 */
5989             default:
5990               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5991               while(--size)
5992                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5993
5994               emitSKPZ;
5995               if(rFalseIfx.condition)
5996                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5997               else
5998                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5999
6000
6001               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
6002               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
6003
6004               rFalseIfx.condition ^= 1;
6005               genSkipc(&rFalseIfx);
6006             }
6007
6008             pic16_emitpLabel(truelbl->key);
6009
6010             if(ifx) ifx->generated = 1;
6011
6012             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6013               goto check_carry;
6014
6015             return;
6016           }
6017
6018
6019           lit++;
6020           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
6021           i = (lit >> (size*8)) & 0xff;
6022
6023           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6024           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6025
6026           while(size--) {
6027             i = (lit >> (size*8)) & 0xff;
6028
6029             if(i) {
6030               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
6031               emitSKPNZ;
6032               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
6033             } else {
6034               /* this byte of the lit is zero, 
6035                * if it's not the last then OR in the variable */
6036               if(size)
6037                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
6038             }
6039           }
6040
6041
6042           pic16_emitpLabel(lbl->key);
6043
6044           rFalseIfx.condition ^= 1;
6045
6046           genSkipc(&rFalseIfx);
6047         }
6048
6049         if(sign)
6050           pic16_emitpLabel(truelbl->key);
6051         if(ifx) ifx->generated = 1;
6052
6053             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6054               goto check_carry;
6055
6056         return;
6057       }
6058     }
6059     /* Compare two variables */
6060
6061     DEBUGpic16_emitcode(";sign","%d",sign);
6062
6063     size--;
6064     if(sign) {
6065       /* Sigh. thus sucks... */
6066       if(size) {
6067         pCodeOp *pctemp;
6068         
6069         pctemp = pic16_popGetTempReg(1);
6070         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
6071         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6072         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6073         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6074         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
6075         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
6076         pic16_popReleaseTempReg(pctemp, 1);
6077       } else {
6078         /* Signed char comparison */
6079         /* Special thanks to Nikolai Golovchenko for this snippet */
6080         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
6081         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
6082         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
6083         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
6084         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
6085         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6086
6087         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6088         genSkipc(&rFalseIfx);
6089           
6090         if(ifx) ifx->generated = 1;
6091
6092             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6093               goto check_carry;
6094
6095         return;
6096       }
6097
6098     } else {
6099
6100       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6101       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6102     }
6103
6104
6105     /* The rest of the bytes of a multi-byte compare */
6106     while (size) {
6107
6108       emitSKPZ;
6109       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
6110       size--;
6111
6112       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
6113       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
6114
6115
6116     }
6117
6118     pic16_emitpLabel(lbl->key);
6119
6120     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6121     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
6122         (AOP_TYPE(result) == AOP_REG)) {
6123       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
6124       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
6125     } else {
6126       genSkipc(&rFalseIfx);
6127     }         
6128     //genSkipc(&rFalseIfx);
6129     if(ifx) ifx->generated = 1;
6130
6131
6132             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
6133               goto check_carry;
6134
6135     return;
6136
6137   }
6138
6139 check_carry:
6140   if ((AOP_TYPE(result) != AOP_CRY) 
6141         && AOP_SIZE(result)) {
6142     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6143
6144     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
6145
6146     pic16_outBitC(result);
6147   } else {
6148     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6149     /* if the result is used in the next
6150        ifx conditional branch then generate
6151        code a little differently */
6152     if (ifx )
6153       genIfxJump (ifx,"c");
6154     else
6155       pic16_outBitC(result);
6156     /* leave the result in acc */
6157   }
6158
6159 }
6160
6161 #elif 0 /* VR version of genCmp() */    /* } else { */
6162
6163 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
6164 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
6165         operand *result, int offset, int invert_op)
6166 {
6167   /* add code here */
6168   
6169   /* check condition, > or < ?? */
6170   if(rIfx->condition != 0)invert_op ^= 1;
6171   
6172   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
6173
6174   if(!ifx)invert_op ^= 1;
6175
6176   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
6177       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
6178   
6179   /* do selection */
6180   if(!invert_op)return POC_CPFSGT;
6181   else return POC_CPFSLT;
6182 }
6183
6184 static int compareAopfirstpass=1;
6185
6186 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
6187             operand *oper, int offset, operand *result,
6188             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
6189             symbol *tlbl)
6190 {
6191   int op;
6192   symbol *truelbl;
6193
6194   /* invert if there is a result to be loaded, in order to fit,
6195    * SETC/CLRC sequence */
6196   if(AOP_SIZE(result))invert_op ^= 1;
6197
6198 //  if(sign && !offset)invert_op ^= 1;
6199   
6200 //  if(sign)invert_op ^= 1;
6201   
6202   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
6203
6204   if(AOP_SIZE(result) && compareAopfirstpass) {
6205     if(!ifx) {
6206       if(pcop2)
6207         pic16_emitpcode(POC_SETF, pcop2);
6208       else
6209         emitSETC;
6210     } else {
6211       if(pcop2)
6212         pic16_emitpcode(POC_CLRF, pcop2);
6213       else
6214         emitCLRC;
6215     }
6216   }
6217
6218   compareAopfirstpass = 0;
6219
6220       /* there is a bug when comparing operands with size > 1,
6221        * because higher bytes can be equal and test should be performed
6222        * to the next lower byte, current algorithm, considers operands
6223        * inequal in these cases! -- VR 20041107 */
6224
6225     
6226   if(pcop)
6227     pic16_emitpcode(op, pcop);
6228   else
6229     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
6230
6231
6232   if((!sign || !offset) && AOP_SIZE(result)) {
6233     if(!ifx) {
6234       if(pcop2)
6235         pic16_emitpcode(POC_CLRF, pcop2);
6236         else
6237         emitCLRC;
6238     } else {
6239       if(pcop2)
6240         pic16_emitpcode(POC_SETF, pcop2);
6241       else
6242         emitSETC;
6243     }
6244     
6245     /* don't emit final branch (offset == 0) */
6246     if(offset) {
6247
6248       if(pcop2)
6249         pic16_emitpcode(POC_RRCF, pcop2);
6250
6251       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6252     }
6253   } else {
6254     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6255       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6256             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6257
6258       truelbl = newiTempLabel( NULL );
6259       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6260       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6261         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6262       else
6263         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6264       pic16_emitpLabel(truelbl->key);
6265     } else {
6266       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6267     }
6268   }
6269 }
6270
6271 static void genCmp (operand *left, operand *right,
6272                     operand *result, iCode *ifx, int sign)
6273 {
6274   int size, cmpop=1;
6275   long lit = 0L;
6276   resolvedIfx rFalseIfx;
6277   symbol *falselbl, *tlbl;
6278
6279     FENTRY;
6280     
6281     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6282
6283     resolveIfx(&rFalseIfx, ifx);
6284     size = max(AOP_SIZE(left), AOP_SIZE(right));
6285     
6286     /* if left & right are bit variables */
6287     if(AOP_TYPE(left) == AOP_CRY
6288       && AOP_TYPE(right) == AOP_CRY ) {
6289
6290         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6291         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6292         
6293         werror(W_POSSBUG2, __FILE__, __LINE__);
6294         exit(EXIT_FAILURE);
6295     }
6296     
6297     /* if literal is on the right then swap with left */
6298     if((AOP_TYPE(right) == AOP_LIT)) {
6299       operand *tmp = right ;
6300 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6301
6302         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6303
6304 //      lit = (lit - 1) & mask;
6305         right = left;
6306         left = tmp;
6307         rFalseIfx.condition ^= 1;               /* reverse compare */
6308     } else
6309     if ((AOP_TYPE(left) == AOP_LIT)) {
6310       /* float compares are handled by support functions */
6311       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6312     }
6313
6314     /* actual comparing algorithm */
6315 //    size = AOP_SIZE( right );
6316
6317     falselbl = newiTempLabel( NULL );
6318     if(AOP_TYPE(left) == AOP_LIT) {
6319       /* compare to literal */
6320       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6321       
6322       if(sign) {
6323         pCodeOp *pct, *pct2;
6324         symbol *tlbl1;
6325
6326         /* signed compare */
6327         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6328
6329         /* using PRODL:PRODH as a temporary register here */
6330         pct = pic16_popCopyReg(&pic16_pc_prodl);
6331         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6332         tlbl = newiTempLabel( NULL );
6333         
6334         /* first compare signs:
6335          *  a. if both are positive, compare just like unsigned
6336          *  b. if both are negative, invert cmpop, compare just like unsigned
6337          *  c. if different signs, determine the result directly */
6338
6339         size--;
6340
6341 #if 1
6342         /* { */
6343         tlbl1 = newiTempLabel( NULL );
6344 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6345
6346         if(lit > 0) {
6347
6348           /* literal is zero or positive:
6349            *  a. if carry is zero, too, continue compare,
6350            *  b. if carry is set, then continue depending on cmpop ^ condition:
6351            *    1. '<' return false (literal < variable),
6352            *    2. '>' return true (literal > variable) */
6353 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6354           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6355           
6356           
6357           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6358           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6359         } else 
6360         if(lit < 0) {
6361           
6362           /* literal is negative:
6363            *  a. if carry is set, too, continue compare,
6364            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6365            *    1. '<' return true (literal < variable),
6366            *    2. '>' return false (literal > variable) */
6367 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6368           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6369           
6370           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6371           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6372         }
6373 #if 1
6374         else {
6375           /* lit == 0 */
6376           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6377           
6378           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6379           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6380         }
6381 #endif
6382         
6383         
6384         pic16_emitpLabel( tlbl1->key );
6385 #endif  /* } */
6386
6387         compareAopfirstpass=1;
6388 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6389 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6390 //        pic16_emitpcode(POC_MOVWF, pct);
6391
6392 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6393         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6394 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6395         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6396
6397         /* generic case */        
6398           while( size-- ) {
6399 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6400 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6401 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6402 //            pic16_emitpcode(POC_MOVWF, pct);
6403
6404 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6405             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6406             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6407 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6408 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6409           }
6410         
6411         if(ifx)ifx->generated = 1;
6412
6413         if(AOP_SIZE(result)) {
6414           pic16_emitpLabel(tlbl->key);
6415           pic16_emitpLabel(falselbl->key);
6416           pic16_outBitOp( result, pct2 );
6417         } else {
6418           pic16_emitpLabel(tlbl->key);
6419         }
6420       } else {
6421
6422         /* unsigned compare */      
6423         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6424     
6425         compareAopfirstpass=1;
6426         while(size--) {
6427           
6428           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6429           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6430
6431         }
6432         if(ifx)ifx->generated = 1;
6433
6434         if(AOP_SIZE(result)) {
6435           pic16_emitpLabel(falselbl->key);
6436           pic16_outBitC( result );
6437         }
6438
6439       }
6440     } else {
6441       /* compare registers */
6442       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6443
6444
6445       if(sign) {
6446         pCodeOp *pct, *pct2;
6447         
6448         /* signed compare */
6449         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6450
6451         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6452         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6453         tlbl = newiTempLabel( NULL );
6454         
6455         compareAopfirstpass=1;
6456
6457         size--;
6458         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6459 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6460         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6461         pic16_emitpcode(POC_MOVWF, pct);
6462
6463         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6464 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6465         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6466
6467         /* WREG already holds left + 0x80 */
6468         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6469         
6470         while( size-- ) {
6471           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6472 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6473           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6474           pic16_emitpcode(POC_MOVWF, pct);
6475                 
6476           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6477 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6478           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6479
6480           /* WREG already holds left + 0x80 */
6481           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6482 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6483         }
6484         
6485         if(ifx)ifx->generated = 1;
6486
6487         if(AOP_SIZE(result)) {
6488           pic16_emitpLabel(tlbl->key);
6489           pic16_emitpLabel(falselbl->key);
6490           pic16_outBitOp( result, pct2 );
6491         } else {
6492           pic16_emitpLabel(tlbl->key);
6493         }
6494
6495       } else {
6496         /* unsigned compare */      
6497         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6498
6499         compareAopfirstpass=1;
6500         while(size--) {
6501           
6502           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6503           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6504
6505         }
6506
6507         if(ifx)ifx->generated = 1;
6508         if(AOP_SIZE(result)) {
6509
6510           pic16_emitpLabel(falselbl->key);
6511           pic16_outBitC( result );
6512         }
6513
6514       }
6515     }
6516 }
6517
6518 #endif  /* } */
6519
6520
6521
6522 /*-----------------------------------------------------------------*/
6523 /* genCmpGt :- greater than comparison                             */
6524 /*-----------------------------------------------------------------*/
6525 static void genCmpGt (iCode *ic, iCode *ifx)
6526 {
6527   operand *left, *right, *result;
6528   sym_link *letype , *retype;
6529   int sign ;
6530
6531     FENTRY;
6532     
6533     left = IC_LEFT(ic);
6534     right= IC_RIGHT(ic);
6535     result = IC_RESULT(ic);
6536
6537     letype = getSpec(operandType(left));
6538     retype =getSpec(operandType(right));
6539     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6540     /* assign the amsops */
6541     pic16_aopOp (left,ic,FALSE);
6542     pic16_aopOp (right,ic,FALSE);
6543     pic16_aopOp (result,ic,TRUE);
6544
6545     genCmp(right, left, result, ifx, sign);
6546
6547     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6548     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6549     pic16_freeAsmop(result,NULL,ic,TRUE); 
6550 }
6551
6552 /*-----------------------------------------------------------------*/
6553 /* genCmpLt - less than comparisons                                */
6554 /*-----------------------------------------------------------------*/
6555 static void genCmpLt (iCode *ic, iCode *ifx)
6556 {
6557   operand *left, *right, *result;
6558   sym_link *letype , *retype;
6559   int sign ;
6560
6561     FENTRY;
6562
6563     left = IC_LEFT(ic);
6564     right= IC_RIGHT(ic);
6565     result = IC_RESULT(ic);
6566
6567     letype = getSpec(operandType(left));
6568     retype =getSpec(operandType(right));
6569     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6570
6571     /* assign the amsops */
6572     pic16_aopOp (left,ic,FALSE);
6573     pic16_aopOp (right,ic,FALSE);
6574     pic16_aopOp (result,ic,TRUE);
6575
6576     genCmp(left, right, result, ifx, sign);
6577
6578     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6579     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6580     pic16_freeAsmop(result,NULL,ic,TRUE); 
6581 }
6582
6583 #if 0
6584 // not needed ATM
6585 // FIXME reenable literal optimisation when the pic16 port is stable
6586
6587 /*-----------------------------------------------------------------*/
6588 /* genc16bit2lit - compare a 16 bit value to a literal             */
6589 /*-----------------------------------------------------------------*/
6590 static void genc16bit2lit(operand *op, int lit, int offset)
6591 {
6592   int i;
6593
6594   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6595   if( (lit&0xff) == 0) 
6596     i=1;
6597   else
6598     i=0;
6599
6600   switch( BYTEofLONG(lit,i)) { 
6601   case 0:
6602     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6603     break;
6604   case 1:
6605     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6606     break;
6607   case 0xff:
6608     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6609     break;
6610   default:
6611     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6612     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6613   }
6614
6615   i ^= 1;
6616
6617   switch( BYTEofLONG(lit,i)) { 
6618   case 0:
6619     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6620     break;
6621   case 1:
6622     emitSKPNZ;
6623     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6624     break;
6625   case 0xff:
6626     emitSKPNZ;
6627     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6628     break;
6629   default:
6630     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6631     emitSKPNZ;
6632     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6633
6634   }
6635
6636 }
6637 #endif
6638
6639 #if 0
6640 // not needed ATM
6641 /*-----------------------------------------------------------------*/
6642 /* gencjneshort - compare and jump if not equal                    */
6643 /*-----------------------------------------------------------------*/
6644 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6645 {
6646   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6647   int offset = 0;
6648   int res_offset = 0;  /* the result may be a different size then left or right */
6649   int res_size = AOP_SIZE(result);
6650   resolvedIfx rIfx;
6651   symbol *lbl, *lbl_done;
6652
6653   unsigned long lit = 0L;
6654   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6655
6656   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6657   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6658   if(result)
6659     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6660   resolveIfx(&rIfx,ifx);
6661   lbl =  newiTempLabel(NULL);
6662   lbl_done =  newiTempLabel(NULL);
6663
6664
6665   /* if the left side is a literal or 
6666      if the right is in a pointer register and left 
6667      is not */
6668   if ((AOP_TYPE(left) == AOP_LIT) || 
6669       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6670     operand *t = right;
6671     right = left;
6672     left = t;
6673   }
6674   if(AOP_TYPE(right) == AOP_LIT)
6675     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6676
6677   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6678     preserve_result = 1;
6679
6680   if(result && !preserve_result)
6681     {
6682       int i;
6683       for(i = 0; i < AOP_SIZE(result); i++)
6684         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6685     }
6686
6687
6688   /* if the right side is a literal then anything goes */
6689   if (AOP_TYPE(right) == AOP_LIT &&
6690       AOP_TYPE(left) != AOP_DIR ) {
6691     switch(size) {
6692     case 2:
6693       genc16bit2lit(left, lit, 0);
6694       emitSKPZ;
6695       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6696       break;
6697     default:
6698       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6699       while (size--) {
6700         if(lit & 0xff) {
6701           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6702           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6703         } else {
6704           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6705         }
6706
6707         emitSKPZ;
6708         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6709         offset++;
6710         if(res_offset < res_size-1)
6711           res_offset++;
6712         lit >>= 8;
6713       }
6714       break;
6715     }
6716   }
6717
6718   /* if the right side is in a register or in direct space or
6719      if the left is a pointer register & right is not */    
6720   else if (AOP_TYPE(right) == AOP_REG ||
6721            AOP_TYPE(right) == AOP_DIR || 
6722            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6723            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6724     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6725     int lbl_key = lbl->key;
6726
6727     if(result) {
6728       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6729       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6730     }else {
6731       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6732       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6733               __FUNCTION__,__LINE__);
6734       return;
6735     }
6736    
6737 /*     switch(size) { */
6738 /*     case 2: */
6739 /*       genc16bit2lit(left, lit, 0); */
6740 /*       emitSKPNZ; */
6741 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6742 /*       break; */
6743 /*     default: */
6744     while (size--) {
6745       int emit_skip=1;
6746       if((AOP_TYPE(left) == AOP_DIR) && 
6747          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6748
6749         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6750         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6751
6752       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6753             
6754         switch (lit & 0xff) {
6755         case 0:
6756           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6757           break;
6758         case 1:
6759           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6760           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6761           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6762           emit_skip=0;
6763           break;
6764         case 0xff:
6765           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6766           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6767           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6768           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6769           emit_skip=0;
6770           break;
6771         default:
6772           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6773           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6774         }
6775         lit >>= 8;
6776
6777       } else {
6778         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6779       }
6780       if(emit_skip) {
6781         if(AOP_TYPE(result) == AOP_CRY) {
6782           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6783           if(rIfx.condition)
6784             emitSKPNZ;
6785           else
6786             emitSKPZ;
6787           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6788         } else {
6789           /* fix me. probably need to check result size too */
6790           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6791           if(rIfx.condition)
6792             emitSKPZ;
6793           else
6794             emitSKPNZ;
6795           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6796           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6797         }
6798         if(ifx)
6799           ifx->generated=1;
6800       }
6801       emit_skip++;
6802       offset++;
6803       if(res_offset < res_size-1)
6804         res_offset++;
6805     }
6806 /*       break; */
6807 /*     } */
6808   } else if(AOP_TYPE(right) == AOP_REG &&
6809             AOP_TYPE(left) != AOP_DIR){
6810
6811     while(size--) {
6812       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6813       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6814       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6815       if(rIfx.condition)
6816         emitSKPNZ;
6817       else
6818         emitSKPZ;
6819       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6820       offset++;
6821       if(res_offset < res_size-1)
6822         res_offset++;
6823     }
6824       
6825   }else{
6826     /* right is a pointer reg need both a & b */
6827     while(size--) {
6828       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6829       if(strcmp(l,"b"))
6830         pic16_emitcode("mov","b,%s",l);
6831       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6832       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6833       offset++;
6834     }
6835   }
6836
6837   if(result && preserve_result)
6838     {
6839       int i;
6840       for(i = 0; i < AOP_SIZE(result); i++)
6841         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6842     }
6843
6844   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6845
6846   if(result && preserve_result)
6847     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6848
6849   if(!rIfx.condition)
6850     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6851
6852   pic16_emitpLabel(lbl->key);
6853
6854   if(result && preserve_result)
6855     {
6856       int i;
6857       for(i = 0; i < AOP_SIZE(result); i++)
6858         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6859
6860       pic16_emitpLabel(lbl_done->key);
6861    }
6862
6863   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6864
6865   if(ifx)
6866     ifx->generated = 1;
6867 }
6868 #endif
6869
6870 #if 0
6871 /*-----------------------------------------------------------------*/
6872 /* gencjne - compare and jump if not equal                         */
6873 /*-----------------------------------------------------------------*/
6874 static void gencjne(operand *left, operand *right, iCode *ifx)
6875 {
6876     symbol *tlbl  = newiTempLabel(NULL);
6877
6878     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6879     gencjneshort(left, right, lbl);
6880
6881     pic16_emitcode("mov","a,%s",one);
6882     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6883     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6884     pic16_emitcode("clr","a");
6885     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6886
6887     pic16_emitpLabel(lbl->key);
6888     pic16_emitpLabel(tlbl->key);
6889
6890 }
6891 #endif
6892
6893
6894 /*-----------------------------------------------------------------*/
6895 /* is_LitOp - check if operand has to be treated as literal        */
6896 /*-----------------------------------------------------------------*/
6897 static bool is_LitOp(operand *op)
6898 {
6899   return ((AOP_TYPE(op) == AOP_LIT)
6900       || ( (AOP_TYPE(op) == AOP_PCODE)
6901           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6902               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6903 }
6904
6905 /*-----------------------------------------------------------------*/
6906 /* is_LitAOp - check if operand has to be treated as literal        */
6907 /*-----------------------------------------------------------------*/
6908 static bool is_LitAOp(asmop *aop)
6909 {
6910   return ((aop->type == AOP_LIT)
6911       || ( (aop->type == AOP_PCODE)
6912           && ( (aop->aopu.pcop->type == PO_LITERAL)
6913               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6914 }
6915
6916
6917
6918 /*-----------------------------------------------------------------*/
6919 /* genCmpEq - generates code for equal to                          */
6920 /*-----------------------------------------------------------------*/
6921 static void genCmpEq (iCode *ic, iCode *ifx)
6922 {
6923   operand *left, *right, *result;
6924   symbol *falselbl = newiTempLabel(NULL);
6925   symbol *donelbl = newiTempLabel(NULL);
6926
6927   int preserve_result = 0;
6928   int generate_result = 0;
6929   int i=0;
6930   unsigned long lit = -1;
6931
6932   FENTRY;
6933   
6934   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6935   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6936   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6937  
6938   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6939
6940   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6941     {
6942       werror(W_POSSBUG2, __FILE__, __LINE__);
6943       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6944       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6945       goto release;
6946     }
6947
6948   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6949     {
6950       operand *tmp = right ;
6951       right = left;
6952       left = tmp;
6953     }
6954
6955   if (AOP_TYPE(right) == AOP_LIT) {
6956     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6957   }
6958
6959   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6960     preserve_result = 1;
6961
6962   if(result && AOP_SIZE(result))
6963     generate_result = 1;
6964
6965   if(generate_result && !preserve_result)
6966     {
6967       for(i = 0; i < AOP_SIZE(result); i++)
6968         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6969     }
6970
6971   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6972   for(i=0; i < AOP_SIZE(left); i++)
6973     {
6974       if(AOP_TYPE(left) != AOP_ACC)
6975         {
6976           if(is_LitOp(left))
6977             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6978           else
6979             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6980         }
6981       if(is_LitOp(right)) {
6982         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6983           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6984         }
6985       } else
6986         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6987
6988       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6989     }
6990
6991   // result == true
6992
6993   if(generate_result && preserve_result)
6994     {
6995       for(i = 0; i < AOP_SIZE(result); i++)
6996         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6997     }
6998
6999   if(generate_result)
7000     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
7001
7002   if(generate_result && preserve_result)
7003     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7004
7005   if(ifx && IC_TRUE(ifx))
7006     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7007
7008   if(ifx && IC_FALSE(ifx))
7009     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
7010
7011   pic16_emitpLabel(falselbl->key);
7012
7013   // result == false
7014
7015   if(ifx && IC_FALSE(ifx))
7016     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7017
7018   if(generate_result && preserve_result)
7019     {
7020       for(i = 0; i < AOP_SIZE(result); i++)
7021         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
7022     }
7023
7024   pic16_emitpLabel(donelbl->key);
7025
7026   if(ifx)
7027     ifx->generated = 1;
7028
7029 release:
7030   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7031   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7032   pic16_freeAsmop(result,NULL,ic,TRUE);
7033
7034 }
7035
7036
7037 #if 0
7038 // old version kept for reference
7039
7040 /*-----------------------------------------------------------------*/
7041 /* genCmpEq - generates code for equal to                          */
7042 /*-----------------------------------------------------------------*/
7043 static void genCmpEq (iCode *ic, iCode *ifx)
7044 {
7045     operand *left, *right, *result;
7046     unsigned long lit = 0L;
7047     int size,offset=0;
7048     symbol *falselbl  = newiTempLabel(NULL);
7049
7050
7051     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7052
7053     if(ifx)
7054       DEBUGpic16_emitcode ("; ifx is non-null","");
7055     else
7056       DEBUGpic16_emitcode ("; ifx is null","");
7057
7058     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7059     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7060     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7061
7062     size = max(AOP_SIZE(left),AOP_SIZE(right));
7063
7064     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7065
7066     /* if literal, literal on the right or 
7067     if the right is in a pointer register and left 
7068     is not */
7069     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
7070         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
7071       operand *tmp = right ;
7072       right = left;
7073       left = tmp;
7074     }
7075
7076
7077     if(ifx && !AOP_SIZE(result)){
7078         symbol *tlbl;
7079         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
7080         /* if they are both bit variables */
7081         if (AOP_TYPE(left) == AOP_CRY &&
7082             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7083                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
7084             if(AOP_TYPE(right) == AOP_LIT){
7085                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7086                 if(lit == 0L){
7087                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7088                     pic16_emitcode("cpl","c");
7089                 } else if(lit == 1L) {
7090                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7091                 } else {
7092                     pic16_emitcode("clr","c");
7093                 }
7094                 /* AOP_TYPE(right) == AOP_CRY */
7095             } else {
7096                 symbol *lbl = newiTempLabel(NULL);
7097                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7098                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7099                 pic16_emitcode("cpl","c");
7100                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7101             }
7102             /* if true label then we jump if condition
7103             supplied is true */
7104             tlbl = newiTempLabel(NULL);
7105             if ( IC_TRUE(ifx) ) {
7106                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
7107                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
7108             } else {
7109                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
7110                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
7111             }
7112             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7113
7114                 {
7115                 /* left and right are both bit variables, result is carry */
7116                         resolvedIfx rIfx;
7117               
7118                         resolveIfx(&rIfx,ifx);
7119
7120                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
7121                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
7122                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
7123                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
7124                         genSkipz2(&rIfx,0);
7125                 }
7126         } else {
7127
7128                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
7129
7130                         /* They're not both bit variables. Is the right a literal? */
7131                         if(AOP_TYPE(right) == AOP_LIT) {
7132                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7133             
7134                         switch(size) {
7135
7136                                 case 1:
7137                                         switch(lit & 0xff) {
7138                                                 case 1:
7139                                                                 if ( IC_TRUE(ifx) ) {
7140                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
7141                                                                         emitSKPNZ;
7142                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7143                                                                 } else {
7144                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
7145                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7146                                                                 }
7147                                                                 break;
7148                                                 case 0xff:
7149                                                                 if ( IC_TRUE(ifx) ) {
7150                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
7151                                                                         emitSKPNZ;
7152                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7153                                                                 } else {
7154                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
7155                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7156                                                                 }
7157                                                                 break;
7158                                                 default:
7159                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7160                                                                 if(lit)
7161                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
7162                                                                 genSkip(ifx,'z');
7163                                         } // switch lit
7164
7165
7166                                         /* end of size == 1 */
7167                                         break;
7168               
7169                                 case 2:
7170                                         genc16bit2lit(left,lit,offset);
7171                                         genSkip(ifx,'z');
7172                                         break;
7173                                         /* end of size == 2 */
7174
7175                                 default:
7176                                         /* size is 4 */
7177                                         if(lit==0) {
7178                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7179                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
7180                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7181                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7182                                                 genSkip(ifx,'z');
7183                                         } else {
7184                                                 /* search for patterns that can be optimized */
7185
7186                                                 genc16bit2lit(left,lit,0);
7187                                                 lit >>= 16;
7188                                                 if(lit) {
7189                                                                 if(IC_TRUE(ifx))
7190                                                                 emitSKPZ; // if hi word unequal
7191                                                                 else
7192                                                                 emitSKPNZ; // if hi word equal
7193                                                                 // fail early
7194                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
7195                                                         genc16bit2lit(left,lit,2);
7196                                                         genSkip(ifx,'z');
7197                                                 } else {
7198                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
7199                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
7200                                                         genSkip(ifx,'z');
7201                                                 }
7202                                         }
7203                                                 pic16_emitpLabel(falselbl->key);
7204                                                 break;
7205
7206                         } // switch size
7207           
7208                         ifx->generated = 1;
7209                         goto release ;
7210             
7211
7212           } else if(AOP_TYPE(right) == AOP_CRY ) {
7213             /* we know the left is not a bit, but that the right is */
7214             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7215             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
7216                       pic16_popGet(AOP(right),offset));
7217             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
7218
7219             /* if the two are equal, then W will be 0 and the Z bit is set
7220              * we could test Z now, or go ahead and check the high order bytes if
7221              * the variable we're comparing is larger than a byte. */
7222
7223             while(--size)
7224               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
7225
7226             if ( IC_TRUE(ifx) ) {
7227               emitSKPNZ;
7228               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7229               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7230             } else {
7231               emitSKPZ;
7232               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7233               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7234             }
7235
7236           } else {
7237             /* They're both variables that are larger than bits */
7238             int s = size;
7239
7240             tlbl = newiTempLabel(NULL);
7241
7242             while(size--) {
7243               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7244               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7245
7246               if ( IC_TRUE(ifx) ) {
7247                 if(size) {
7248                   emitSKPZ;
7249                 
7250                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7251
7252                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7253                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7254                 } else {
7255                   emitSKPNZ;
7256
7257                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7258
7259
7260                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7261                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7262                 }
7263               } else {
7264                 emitSKPZ;
7265
7266                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7267
7268                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7269                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7270               }
7271               offset++;
7272             }
7273             if(s>1 && IC_TRUE(ifx)) {
7274               pic16_emitpLabel(tlbl->key);
7275               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7276             }
7277           }
7278         }
7279         /* mark the icode as generated */
7280         ifx->generated = 1;
7281         goto release ;
7282     }
7283
7284     /* if they are both bit variables */
7285     if (AOP_TYPE(left) == AOP_CRY &&
7286         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7287         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7288         if(AOP_TYPE(right) == AOP_LIT){
7289             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7290             if(lit == 0L){
7291                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7292                 pic16_emitcode("cpl","c");
7293             } else if(lit == 1L) {
7294                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7295             } else {
7296                 pic16_emitcode("clr","c");
7297             }
7298             /* AOP_TYPE(right) == AOP_CRY */
7299         } else {
7300             symbol *lbl = newiTempLabel(NULL);
7301             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7302             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7303             pic16_emitcode("cpl","c");
7304             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7305         }
7306         /* c = 1 if egal */
7307         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7308             pic16_outBitC(result);
7309             goto release ;
7310         }
7311         if (ifx) {
7312             genIfxJump (ifx,"c");
7313             goto release ;
7314         }
7315         /* if the result is used in an arithmetic operation
7316         then put the result in place */
7317         pic16_outBitC(result);
7318     } else {
7319       
7320       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7321       gencjne(left,right,result,ifx);
7322 /*
7323       if(ifx) 
7324         gencjne(left,right,newiTempLabel(NULL));
7325       else {
7326         if(IC_TRUE(ifx)->key)
7327           gencjne(left,right,IC_TRUE(ifx)->key);
7328         else
7329           gencjne(left,right,IC_FALSE(ifx)->key);
7330         ifx->generated = 1;
7331         goto release ;
7332       }
7333       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7334         pic16_aopPut(AOP(result),"a",0);
7335         goto release ;
7336       }
7337
7338       if (ifx) {
7339         genIfxJump (ifx,"a");
7340         goto release ;
7341       }
7342 */
7343       /* if the result is used in an arithmetic operation
7344          then put the result in place */
7345 /*
7346       if (AOP_TYPE(result) != AOP_CRY) 
7347         pic16_outAcc(result);
7348 */
7349       /* leave the result in acc */
7350     }
7351
7352 release:
7353     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7354     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7355     pic16_freeAsmop(result,NULL,ic,TRUE);
7356 }
7357 #endif
7358
7359 /*-----------------------------------------------------------------*/
7360 /* ifxForOp - returns the icode containing the ifx for operand     */
7361 /*-----------------------------------------------------------------*/
7362 static iCode *ifxForOp ( operand *op, iCode *ic )
7363 {
7364   FENTRY2;
7365
7366     /* if true symbol then needs to be assigned */
7367     if (IS_TRUE_SYMOP(op))
7368         return NULL ;
7369
7370     /* if this has register type condition and
7371     the next instruction is ifx with the same operand
7372     and live to of the operand is upto the ifx only then */
7373     if (ic->next
7374         && ic->next->op == IFX
7375         && IC_COND(ic->next)->key == op->key
7376         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7377         ) {
7378                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7379           return ic->next;
7380     }
7381
7382     /*
7383     if (ic->next &&
7384         ic->next->op == IFX &&
7385         IC_COND(ic->next)->key == op->key) {
7386       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7387       return ic->next;
7388     }
7389     */
7390
7391     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7392     if (ic->next &&
7393         ic->next->op == IFX)
7394       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7395
7396     if (ic->next &&
7397         ic->next->op == IFX &&
7398         IC_COND(ic->next)->key == op->key) {
7399       DEBUGpic16_emitcode ("; "," key is okay");
7400       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7401                            OP_SYMBOL(op)->liveTo,
7402                            ic->next->seq);
7403     }
7404
7405 #if 0
7406     /* the code below is completely untested
7407      * it just allows ulong2fs.c compile -- VR */
7408          
7409     ic = ic->next;
7410     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7411                                         __FILE__, __FUNCTION__, __LINE__);
7412         
7413     /* if this has register type condition and
7414     the next instruction is ifx with the same operand
7415     and live to of the operand is upto the ifx only then */
7416     if (ic->next &&
7417         ic->next->op == IFX &&
7418         IC_COND(ic->next)->key == op->key &&
7419         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7420         return ic->next;
7421
7422     if (ic->next &&
7423         ic->next->op == IFX &&
7424         IC_COND(ic->next)->key == op->key) {
7425       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7426       return ic->next;
7427     }
7428
7429     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7430                                         __FILE__, __FUNCTION__, __LINE__);
7431
7432 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7433 #endif
7434
7435     return NULL;
7436 }
7437 /*-----------------------------------------------------------------*/
7438 /* genAndOp - for && operation                                     */
7439 /*-----------------------------------------------------------------*/
7440 static void genAndOp (iCode *ic)
7441 {
7442   operand *left,*right, *result;
7443 /*     symbol *tlbl; */
7444
7445     FENTRY;
7446
7447     /* note here that && operations that are in an
7448     if statement are taken away by backPatchLabels
7449     only those used in arthmetic operations remain */
7450     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7451     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7452     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7453
7454     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7455
7456     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7457     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7458     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7459
7460     /* if both are bit variables */
7461 /*     if (AOP_TYPE(left) == AOP_CRY && */
7462 /*         AOP_TYPE(right) == AOP_CRY ) { */
7463 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7464 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7465 /*         pic16_outBitC(result); */
7466 /*     } else { */
7467 /*         tlbl = newiTempLabel(NULL); */
7468 /*         pic16_toBoolean(left);     */
7469 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7470 /*         pic16_toBoolean(right); */
7471 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7472 /*         pic16_outBitAcc(result); */
7473 /*     } */
7474
7475     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7476     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7477     pic16_freeAsmop(result,NULL,ic,TRUE);
7478 }
7479
7480
7481 /*-----------------------------------------------------------------*/
7482 /* genOrOp - for || operation                                      */
7483 /*-----------------------------------------------------------------*/
7484 /*
7485   tsd pic port -
7486   modified this code, but it doesn't appear to ever get called
7487 */
7488
7489 static void genOrOp (iCode *ic)
7490 {
7491   operand *left,*right, *result;
7492   symbol *tlbl;
7493
7494     FENTRY;  
7495
7496   /* note here that || operations that are in an
7497     if statement are taken away by backPatchLabels
7498     only those used in arthmetic operations remain */
7499     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7500     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7501     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7502
7503     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7504
7505     /* if both are bit variables */
7506     if (AOP_TYPE(left) == AOP_CRY &&
7507         AOP_TYPE(right) == AOP_CRY ) {
7508       pic16_emitcode("clrc","");
7509       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7510                AOP(left)->aopu.aop_dir,
7511                AOP(left)->aopu.aop_dir);
7512       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7513                AOP(right)->aopu.aop_dir,
7514                AOP(right)->aopu.aop_dir);
7515       pic16_emitcode("setc","");
7516
7517     } else {
7518         tlbl = newiTempLabel(NULL);
7519         pic16_toBoolean(left);
7520         emitSKPZ;
7521         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7522         pic16_toBoolean(right);
7523         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7524
7525         pic16_outBitAcc(result);
7526     }
7527
7528     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7529     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7530     pic16_freeAsmop(result,NULL,ic,TRUE);            
7531 }
7532
7533 /*-----------------------------------------------------------------*/
7534 /* isLiteralBit - test if lit == 2^n                               */
7535 /*-----------------------------------------------------------------*/
7536 static int isLiteralBit(unsigned long lit)
7537 {
7538     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7539     0x100L,0x200L,0x400L,0x800L,
7540     0x1000L,0x2000L,0x4000L,0x8000L,
7541     0x10000L,0x20000L,0x40000L,0x80000L,
7542     0x100000L,0x200000L,0x400000L,0x800000L,
7543     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7544     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7545     int idx;
7546     
7547     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7548     for(idx = 0; idx < 32; idx++)
7549         if(lit == pw[idx])
7550             return idx+1;
7551     return 0;
7552 }
7553
7554 /*-----------------------------------------------------------------*/
7555 /* continueIfTrue -                                                */
7556 /*-----------------------------------------------------------------*/
7557 static void continueIfTrue (iCode *ic)
7558 {
7559   FENTRY;
7560   if(IC_TRUE(ic))
7561     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7562   ic->generated = 1;
7563 }
7564
7565 /*-----------------------------------------------------------------*/
7566 /* jmpIfTrue -                                                     */
7567 /*-----------------------------------------------------------------*/
7568 static void jumpIfTrue (iCode *ic)
7569 {
7570   FENTRY;
7571   if(!IC_TRUE(ic))
7572     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7573   ic->generated = 1;
7574 }
7575
7576 /*-----------------------------------------------------------------*/
7577 /* jmpTrueOrFalse -                                                */
7578 /*-----------------------------------------------------------------*/
7579 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7580 {
7581   // ugly but optimized by peephole
7582   FENTRY;
7583   if(IC_TRUE(ic)){
7584     symbol *nlbl = newiTempLabel(NULL);
7585       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7586       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7587       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7588       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7589   } else {
7590     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7591     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7592   }
7593   ic->generated = 1;
7594 }
7595
7596 /*-----------------------------------------------------------------*/
7597 /* genAnd  - code for and                                          */
7598 /*-----------------------------------------------------------------*/
7599 static void genAnd (iCode *ic, iCode *ifx)
7600 {
7601   operand *left, *right, *result;
7602   int size, offset=0;  
7603   unsigned long lit = 0L;
7604   int bytelit = 0;
7605   resolvedIfx rIfx;
7606
7607     FENTRY;
7608     
7609   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7610   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7611   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7612
7613   resolveIfx(&rIfx,ifx);
7614
7615   /* if left is a literal & right is not then exchange them */
7616   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7617       AOP_NEEDSACC(left)) {
7618     operand *tmp = right ;
7619     right = left;
7620     left = tmp;
7621   }
7622
7623   /* if result = right then exchange them */
7624   if(pic16_sameRegs(AOP(result),AOP(right))){
7625     operand *tmp = right ;
7626     right = left;
7627     left = tmp;
7628   }
7629
7630   /* if right is bit then exchange them */
7631   if (AOP_TYPE(right) == AOP_CRY &&
7632       AOP_TYPE(left) != AOP_CRY){
7633     operand *tmp = right ;
7634     right = left;
7635     left = tmp;
7636   }
7637   if(AOP_TYPE(right) == AOP_LIT)
7638     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7639
7640   size = AOP_SIZE(result);
7641
7642   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7643
7644   // if(bit & yy)
7645   // result = bit & yy;
7646   if (AOP_TYPE(left) == AOP_CRY){
7647     // c = bit & literal;
7648     if(AOP_TYPE(right) == AOP_LIT){
7649       if(lit & 1) {
7650         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7651           // no change
7652           goto release;
7653         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7654       } else {
7655         // bit(result) = 0;
7656         if(size && (AOP_TYPE(result) == AOP_CRY)){
7657           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7658           goto release;
7659         }
7660         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7661           jumpIfTrue(ifx);
7662           goto release;
7663         }
7664         pic16_emitcode("clr","c");
7665       }
7666     } else {
7667       if (AOP_TYPE(right) == AOP_CRY){
7668         // c = bit & bit;
7669         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7670         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7671       } else {
7672         // c = bit & val;
7673         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7674         // c = lsb
7675         pic16_emitcode("rrc","a");
7676         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7677       }
7678     }
7679     // bit = c
7680     // val = c
7681     if(size)
7682       pic16_outBitC(result);
7683     // if(bit & ...)
7684     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7685       genIfxJump(ifx, "c");           
7686     goto release ;
7687   }
7688
7689   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7690   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7691   if((AOP_TYPE(right) == AOP_LIT) &&
7692      (AOP_TYPE(result) == AOP_CRY) &&
7693      (AOP_TYPE(left) != AOP_CRY)){
7694     int posbit = isLiteralBit(lit);
7695     /* left &  2^n */
7696     if(posbit){
7697       posbit--;
7698       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7699       // bit = left & 2^n
7700       if(size)
7701         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7702       // if(left &  2^n)
7703       else{
7704         if(ifx){
7705 /*
7706           if(IC_TRUE(ifx)) {
7707             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7708             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7709           } else {
7710             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7711             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7712           }
7713 */
7714         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7715         size = AOP_SIZE(left);
7716
7717         {
7718           int bp = posbit, ofs=0;
7719           
7720             while(bp > 7) {
7721               bp -= 8;
7722               ofs++;
7723             }
7724
7725           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7726                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7727
7728         }
7729 /*
7730           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7731                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7732 */
7733           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7734           
7735           ifx->generated = 1;
7736         }
7737         goto release;
7738       }
7739     } else {
7740       symbol *tlbl = newiTempLabel(NULL);
7741       int sizel = AOP_SIZE(left);
7742
7743       if(size)
7744         emitSETC;
7745
7746       while(sizel--) {
7747         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7748
7749           /* patch provided by Aaron Colwell */
7750           if((posbit = isLiteralBit(bytelit)) != 0) {
7751               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7752                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7753                                                 (posbit-1),0, PO_GPR_REGISTER));
7754
7755               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7756 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7757           } else {
7758               if (bytelit == 0xff) {
7759                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7760                    * a peephole could optimize it out -- VR */
7761                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7762               } else {
7763                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7764                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7765               }
7766
7767               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7768                             pic16_popGetLabel(tlbl->key));
7769           }
7770         
7771 #if 0
7772           /* old code, left here for reference -- VR 09/2004 */
7773           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7774           // byte ==  2^n ?
7775           if((posbit = isLiteralBit(bytelit)) != 0)
7776             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7777           else{
7778             if(bytelit != 0x0FFL)
7779               pic16_emitcode("anl","a,%s",
7780                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7781             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7782           }
7783 #endif
7784         }
7785         offset++;
7786       }
7787       // bit = left & literal
7788       if(size) {
7789         emitCLRC;
7790         pic16_emitpLabel(tlbl->key);
7791       }
7792       // if(left & literal)
7793       else {
7794         if(ifx) {
7795           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7796           ifx->generated = 1;
7797         }
7798         pic16_emitpLabel(tlbl->key);
7799         goto release;
7800       }
7801     }
7802
7803     pic16_outBitC(result);
7804     goto release ;
7805   }
7806
7807   /* if left is same as result */
7808   if(pic16_sameRegs(AOP(result),AOP(left))){
7809     int know_W = -1;
7810     for(;size--; offset++,lit>>=8) {
7811       if(AOP_TYPE(right) == AOP_LIT){
7812         switch(lit & 0xff) {
7813         case 0x00:
7814           /*  and'ing with 0 has clears the result */
7815 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7816           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7817           break;
7818         case 0xff:
7819           /* and'ing with 0xff is a nop when the result and left are the same */
7820           break;
7821
7822         default:
7823           {
7824             int p = pic16_my_powof2( (~lit) & 0xff );
7825             if(p>=0) {
7826               /* only one bit is set in the literal, so use a bcf instruction */
7827 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7828               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7829
7830             } else {
7831               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7832               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7833               if(know_W != (lit&0xff))
7834                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7835               know_W = lit &0xff;
7836               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7837             }
7838           }    
7839         }
7840       } else {
7841         if (AOP_TYPE(left) == AOP_ACC) {
7842           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7843         } else {                    
7844           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7845           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7846
7847         }
7848       }
7849     }
7850
7851   } else {
7852     // left & result in different registers
7853     if(AOP_TYPE(result) == AOP_CRY){
7854       // result = bit
7855       // if(size), result in bit
7856       // if(!size && ifx), conditional oper: if(left & right)
7857       symbol *tlbl = newiTempLabel(NULL);
7858       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7859       if(size)
7860         pic16_emitcode("setb","c");
7861       while(sizer--){
7862         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7863         pic16_emitcode("anl","a,%s",
7864                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7865         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7866         offset++;
7867       }
7868       if(size){
7869         CLRC;
7870         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7871         pic16_outBitC(result);
7872       } else if(ifx)
7873         jmpTrueOrFalse(ifx, tlbl);
7874     } else {
7875       for(;(size--);offset++) {
7876         // normal case
7877         // result = left & right
7878         if(AOP_TYPE(right) == AOP_LIT){
7879           int t = (lit >> (offset*8)) & 0x0FFL;
7880           switch(t) { 
7881           case 0x00:
7882             pic16_emitcode("clrf","%s",
7883                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7884             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7885             break;
7886           case 0xff:
7887             pic16_emitcode("movf","%s,w",
7888                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7889             pic16_emitcode("movwf","%s",
7890                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7891             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7892             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7893             break;
7894           default:
7895             pic16_emitcode("movlw","0x%x",t);
7896             pic16_emitcode("andwf","%s,w",
7897                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7898             pic16_emitcode("movwf","%s",
7899                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7900               
7901             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7902             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7903             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7904           }
7905           continue;
7906         }
7907
7908         if (AOP_TYPE(left) == AOP_ACC) {
7909           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7910           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7911         } else {
7912           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7913           pic16_emitcode("andwf","%s,w",
7914                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7915           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7916           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7917         }
7918         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7919         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7920       }
7921     }
7922   }
7923
7924   release :
7925     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7926   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7927   pic16_freeAsmop(result,NULL,ic,TRUE);     
7928 }
7929
7930 /*-----------------------------------------------------------------*/
7931 /* genOr  - code for or                                            */
7932 /*-----------------------------------------------------------------*/
7933 static void genOr (iCode *ic, iCode *ifx)
7934 {
7935     operand *left, *right, *result;
7936     int size, offset=0;
7937     unsigned long lit = 0L;
7938
7939     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7940     FENTRY;
7941
7942     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7943     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7944     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7945
7946     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7947
7948     /* if left is a literal & right is not then exchange them */
7949     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7950         AOP_NEEDSACC(left)) {
7951         operand *tmp = right ;
7952         right = left;
7953         left = tmp;
7954     }
7955
7956     /* if result = right then exchange them */
7957     if(pic16_sameRegs(AOP(result),AOP(right))){
7958         operand *tmp = right ;
7959         right = left;
7960         left = tmp;
7961     }
7962
7963     /* if right is bit then exchange them */
7964     if (AOP_TYPE(right) == AOP_CRY &&
7965         AOP_TYPE(left) != AOP_CRY){
7966         operand *tmp = right ;
7967         right = left;
7968         left = tmp;
7969     }
7970
7971     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7972
7973     if(AOP_TYPE(right) == AOP_LIT)
7974         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7975
7976     size = AOP_SIZE(result);
7977
7978     // if(bit | yy)
7979     // xx = bit | yy;
7980     if (AOP_TYPE(left) == AOP_CRY){
7981         if(AOP_TYPE(right) == AOP_LIT){
7982             // c = bit & literal;
7983             if(lit){
7984                 // lit != 0 => result = 1
7985                 if(AOP_TYPE(result) == AOP_CRY){
7986                   if(size)
7987                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7988                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7989                   //     AOP(result)->aopu.aop_dir,
7990                   //     AOP(result)->aopu.aop_dir);
7991                     else if(ifx)
7992                         continueIfTrue(ifx);
7993                     goto release;
7994                 }
7995             } else {
7996                 // lit == 0 => result = left
7997                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7998                     goto release;
7999                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
8000             }
8001         } else {
8002             if (AOP_TYPE(right) == AOP_CRY){
8003               if(pic16_sameRegs(AOP(result),AOP(left))){
8004                 // c = bit | bit;
8005                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8006                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
8007                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8008
8009                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8010                          AOP(result)->aopu.aop_dir,
8011                          AOP(result)->aopu.aop_dir);
8012                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8013                          AOP(right)->aopu.aop_dir,
8014                          AOP(right)->aopu.aop_dir);
8015                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8016                          AOP(result)->aopu.aop_dir,
8017                          AOP(result)->aopu.aop_dir);
8018               } else {
8019                 if( AOP_TYPE(result) == AOP_ACC) {
8020                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8021                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8022                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8023                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
8024
8025                 } else {
8026
8027                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8028                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
8029                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8030                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8031
8032                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
8033                                  AOP(result)->aopu.aop_dir,
8034                                  AOP(result)->aopu.aop_dir);
8035                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
8036                                  AOP(right)->aopu.aop_dir,
8037                                  AOP(right)->aopu.aop_dir);
8038                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
8039                                  AOP(left)->aopu.aop_dir,
8040                                  AOP(left)->aopu.aop_dir);
8041                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
8042                                  AOP(result)->aopu.aop_dir,
8043                                  AOP(result)->aopu.aop_dir);
8044                 }
8045               }
8046             } else {
8047                 // c = bit | val;
8048                 symbol *tlbl = newiTempLabel(NULL);
8049                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8050
8051
8052                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
8053                 if( AOP_TYPE(right) == AOP_ACC) {
8054                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
8055                   emitSKPNZ;
8056                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
8057                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
8058                 }
8059
8060
8061
8062                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
8063                     pic16_emitcode(";XXX setb","c");
8064                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
8065                          AOP(left)->aopu.aop_dir,tlbl->key+100);
8066                 pic16_toBoolean(right);
8067                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8068                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
8069                     jmpTrueOrFalse(ifx, tlbl);
8070                     goto release;
8071                 } else {
8072                     CLRC;
8073                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8074                 }
8075             }
8076         }
8077         // bit = c
8078         // val = c
8079         if(size)
8080             pic16_outBitC(result);
8081         // if(bit | ...)
8082         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8083             genIfxJump(ifx, "c");           
8084         goto release ;
8085     }
8086
8087     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
8088     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
8089     if((AOP_TYPE(right) == AOP_LIT) &&
8090        (AOP_TYPE(result) == AOP_CRY) &&
8091        (AOP_TYPE(left) != AOP_CRY)){
8092         if(lit){
8093           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8094             // result = 1
8095             if(size)
8096                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
8097             else 
8098                 continueIfTrue(ifx);
8099             goto release;
8100         } else {
8101           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8102             // lit = 0, result = boolean(left)
8103             if(size)
8104                 pic16_emitcode(";XXX setb","c");
8105             pic16_toBoolean(right);
8106             if(size){
8107                 symbol *tlbl = newiTempLabel(NULL);
8108                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8109                 CLRC;
8110                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8111             } else {
8112                 genIfxJump (ifx,"a");
8113                 goto release;
8114             }
8115         }
8116         pic16_outBitC(result);
8117         goto release ;
8118     }
8119
8120     /* if left is same as result */
8121     if(pic16_sameRegs(AOP(result),AOP(left))){
8122       int know_W = -1;
8123       for(;size--; offset++,lit>>=8) {
8124         if(AOP_TYPE(right) == AOP_LIT){
8125           if((lit & 0xff) == 0)
8126             /*  or'ing with 0 has no effect */
8127             continue;
8128           else {
8129             int p = pic16_my_powof2(lit & 0xff);
8130             if(p>=0) {
8131               /* only one bit is set in the literal, so use a bsf instruction */
8132               pic16_emitpcode(POC_BSF,
8133                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
8134             } else {
8135               if(know_W != (lit & 0xff))
8136                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
8137               know_W = lit & 0xff;
8138               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
8139             }
8140                     
8141           }
8142         } else {
8143           if (AOP_TYPE(left) == AOP_ACC) {
8144             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
8145 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8146           } else {                  
8147             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8148             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
8149
8150 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8151 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8152
8153           }
8154         }
8155       }
8156     } else {
8157         // left & result in different registers
8158         if(AOP_TYPE(result) == AOP_CRY){
8159             // result = bit
8160             // if(size), result in bit
8161             // if(!size && ifx), conditional oper: if(left | right)
8162             symbol *tlbl = newiTempLabel(NULL);
8163             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8164             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
8165
8166
8167             if(size)
8168                 pic16_emitcode(";XXX setb","c");
8169             while(sizer--){
8170                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8171                 pic16_emitcode(";XXX orl","a,%s",
8172                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8173                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
8174                 offset++;
8175             }
8176             if(size){
8177                 CLRC;
8178                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8179                 pic16_outBitC(result);
8180             } else if(ifx)
8181                 jmpTrueOrFalse(ifx, tlbl);
8182         } else for(;(size--);offset++){
8183           // normal case
8184           // result = left & right
8185           if(AOP_TYPE(right) == AOP_LIT){
8186             int t = (lit >> (offset*8)) & 0x0FFL;
8187             switch(t) { 
8188             case 0x00:
8189               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8190               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8191
8192 //            pic16_emitcode("movf","%s,w",
8193 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8194 //            pic16_emitcode("movwf","%s",
8195 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8196               break;
8197             default:
8198               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
8199               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8200               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8201
8202 //            pic16_emitcode("movlw","0x%x",t);
8203 //            pic16_emitcode("iorwf","%s,w",
8204 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8205 //            pic16_emitcode("movwf","%s",
8206 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8207               
8208             }
8209             continue;
8210           }
8211
8212           // faster than result <- left, anl result,right
8213           // and better if result is SFR
8214           if (AOP_TYPE(left) == AOP_ACC) {
8215             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
8216 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8217           } else {
8218             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
8219             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
8220
8221 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8222 //          pic16_emitcode("iorwf","%s,w",
8223 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8224           }
8225           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8226 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8227         }
8228     }
8229
8230 release :
8231     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8232     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8233     pic16_freeAsmop(result,NULL,ic,TRUE);     
8234 }
8235
8236 /*-----------------------------------------------------------------*/
8237 /* genXor - code for xclusive or                                   */
8238 /*-----------------------------------------------------------------*/
8239 static void genXor (iCode *ic, iCode *ifx)
8240 {
8241   operand *left, *right, *result;
8242   int size, offset=0;
8243   unsigned long lit = 0L;
8244
8245   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8246   FENTRY;
8247
8248   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8249   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8250   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8251
8252   /* if left is a literal & right is not ||
8253      if left needs acc & right does not */
8254   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8255       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8256     operand *tmp = right ;
8257     right = left;
8258     left = tmp;
8259   }
8260
8261   /* if result = right then exchange them */
8262   if(pic16_sameRegs(AOP(result),AOP(right))){
8263     operand *tmp = right ;
8264     right = left;
8265     left = tmp;
8266   }
8267
8268   /* if right is bit then exchange them */
8269   if (AOP_TYPE(right) == AOP_CRY &&
8270       AOP_TYPE(left) != AOP_CRY){
8271     operand *tmp = right ;
8272     right = left;
8273     left = tmp;
8274   }
8275   if(AOP_TYPE(right) == AOP_LIT)
8276     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8277
8278   size = AOP_SIZE(result);
8279
8280   // if(bit ^ yy)
8281   // xx = bit ^ yy;
8282   if (AOP_TYPE(left) == AOP_CRY){
8283     if(AOP_TYPE(right) == AOP_LIT){
8284       // c = bit & literal;
8285       if(lit>>1){
8286         // lit>>1  != 0 => result = 1
8287         if(AOP_TYPE(result) == AOP_CRY){
8288           if(size)
8289             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8290             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8291           else if(ifx)
8292             continueIfTrue(ifx);
8293           goto release;
8294         }
8295         pic16_emitcode("setb","c");
8296       } else{
8297         // lit == (0 or 1)
8298         if(lit == 0){
8299           // lit == 0, result = left
8300           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8301             goto release;
8302           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8303         } else{
8304           // lit == 1, result = not(left)
8305           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8306             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8307             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8308             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8309             goto release;
8310           } else {
8311             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8312             pic16_emitcode("cpl","c");
8313           }
8314         }
8315       }
8316
8317     } else {
8318       // right != literal
8319       symbol *tlbl = newiTempLabel(NULL);
8320       if (AOP_TYPE(right) == AOP_CRY){
8321         // c = bit ^ bit;
8322         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8323       }
8324       else{
8325         int sizer = AOP_SIZE(right);
8326         // c = bit ^ val
8327         // if val>>1 != 0, result = 1
8328         pic16_emitcode("setb","c");
8329         while(sizer){
8330           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8331           if(sizer == 1)
8332             // test the msb of the lsb
8333             pic16_emitcode("anl","a,#0xfe");
8334           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8335           sizer--;
8336         }
8337         // val = (0,1)
8338         pic16_emitcode("rrc","a");
8339       }
8340       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8341       pic16_emitcode("cpl","c");
8342       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8343     }
8344     // bit = c
8345     // val = c
8346     if(size)
8347       pic16_outBitC(result);
8348     // if(bit | ...)
8349     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8350       genIfxJump(ifx, "c");           
8351     goto release ;
8352   }
8353
8354   if(pic16_sameRegs(AOP(result),AOP(left))){
8355     /* if left is same as result */
8356     for(;size--; offset++) {
8357       if(AOP_TYPE(right) == AOP_LIT){
8358         int t  = (lit >> (offset*8)) & 0x0FFL;
8359         if(t == 0x00L)
8360           continue;
8361         else
8362           if (IS_AOP_PREG(left)) {
8363             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8364             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8365             pic16_aopPut(AOP(result),"a",offset);
8366           } else {
8367             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8368             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8369             pic16_emitcode("xrl","%s,%s",
8370                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8371                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8372           }
8373       } else {
8374         if (AOP_TYPE(left) == AOP_ACC)
8375           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8376         else {
8377           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8378           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8379 /*
8380           if (IS_AOP_PREG(left)) {
8381             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8382             pic16_aopPut(AOP(result),"a",offset);
8383           } else
8384             pic16_emitcode("xrl","%s,a",
8385                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8386 */
8387         }
8388       }
8389     }
8390   } else {
8391     // left & result in different registers
8392     if(AOP_TYPE(result) == AOP_CRY){
8393       // result = bit
8394       // if(size), result in bit
8395       // if(!size && ifx), conditional oper: if(left ^ right)
8396       symbol *tlbl = newiTempLabel(NULL);
8397       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8398       if(size)
8399         pic16_emitcode("setb","c");
8400       while(sizer--){
8401         if((AOP_TYPE(right) == AOP_LIT) &&
8402            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8403           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8404         } else {
8405           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8406           pic16_emitcode("xrl","a,%s",
8407                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8408         }
8409         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8410         offset++;
8411       }
8412       if(size){
8413         CLRC;
8414         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8415         pic16_outBitC(result);
8416       } else if(ifx)
8417         jmpTrueOrFalse(ifx, tlbl);
8418     } else for(;(size--);offset++){
8419       // normal case
8420       // result = left & right
8421       if(AOP_TYPE(right) == AOP_LIT){
8422         int t = (lit >> (offset*8)) & 0x0FFL;
8423         switch(t) { 
8424         case 0x00:
8425           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8426           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8427           pic16_emitcode("movf","%s,w",
8428                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8429           pic16_emitcode("movwf","%s",
8430                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8431           break;
8432         case 0xff:
8433           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8434           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8435           pic16_emitcode("comf","%s,w",
8436                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8437           pic16_emitcode("movwf","%s",
8438                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8439           break;
8440         default:
8441           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8442           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8443           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8444           pic16_emitcode("movlw","0x%x",t);
8445           pic16_emitcode("xorwf","%s,w",
8446                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8447           pic16_emitcode("movwf","%s",
8448                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8449
8450         }
8451         continue;
8452       }
8453
8454       // faster than result <- left, anl result,right
8455       // and better if result is SFR
8456       if (AOP_TYPE(left) == AOP_ACC) {
8457         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8458         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8459       } else {
8460         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8461         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8462         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8463         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8464       }
8465       if ( AOP_TYPE(result) != AOP_ACC){
8466         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8467         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8468       }
8469     }
8470   }
8471
8472   release :
8473     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8474   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8475   pic16_freeAsmop(result,NULL,ic,TRUE);     
8476 }
8477
8478 /*-----------------------------------------------------------------*/
8479 /* genInline - write the inline code out                           */
8480 /*-----------------------------------------------------------------*/
8481 static void genInline (iCode *ic)
8482 {
8483   char *buffer, *bp, *bp1;
8484   bool inComment = FALSE;
8485     
8486   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8487
8488   _G.inLine += (!options.asmpeep);
8489
8490   buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic));
8491   
8492   while((bp1=strstr(bp, "\\n"))) {
8493     *bp1++ = '\n';
8494     *bp1++ = ' ';
8495     bp = bp1;
8496   }
8497   bp = bp1 = buffer;
8498
8499 #if 0
8500   /* This is an experimental code for #pragma inline
8501      and is temporarily disabled for 2.5.0 release */
8502   if(asmInlineMap)
8503   {
8504     symbol *sym;
8505     char *s;
8506     char *cbuf;
8507     int cblen;
8508
8509       cbuf = Safe_strdup(buffer);
8510       cblen = strlen(buffer)+1;
8511       memset(cbuf, 0, cblen);
8512
8513       bp = buffer;
8514       bp1 = cbuf;
8515       while(*bp) {
8516         if(*bp != '%')*bp1++ = *bp++;
8517         else {
8518           int i;
8519
8520             bp++;
8521             i = *bp - '0';
8522             if(i>elementsInSet(asmInlineMap))break;
8523             
8524             bp++;
8525             s = indexSet(asmInlineMap, i);
8526             DEBUGpc("searching symbol s = `%s'", s);
8527             sym = findSym(SymbolTab, NULL, s);
8528
8529             if(sym->reqv) {
8530               strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8531             } else {
8532               strcat(bp1, sym->rname);
8533             }
8534             
8535             while(*bp1)bp1++;
8536         }
8537         
8538         if(strlen(bp1) > cblen - 16) {
8539           int i = strlen(cbuf);
8540           cblen += 50;
8541           cbuf = realloc(cbuf, cblen);
8542           memset(cbuf+i, 0, 50);
8543           bp1 = cbuf + i;
8544         }
8545       }
8546       
8547       free(buffer);
8548       buffer = Safe_strdup( cbuf );
8549       free(cbuf);
8550       
8551       bp = bp1 = buffer;
8552   }
8553 #endif  /* 0 */
8554
8555   /* emit each line as a code */
8556   while (*bp)
8557     {
8558       switch (*bp)
8559         {
8560         case ';':
8561           inComment = TRUE;
8562           ++bp;
8563           break;
8564
8565         case '\n':
8566           inComment = FALSE;
8567           *bp++ = '\0';
8568           if (*bp1)
8569             pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8570           bp1 = bp;
8571           break;
8572
8573         default:
8574           /* Add \n for labels, not dirs such as c:\mydir */
8575           if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1])))
8576             {
8577               ++bp;
8578               *bp = '\0';
8579               ++bp;
8580               /* print label, use this special format with NULL directive
8581                * to denote that the argument should not be indented with tab */
8582               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8583               bp1 = bp;
8584             }
8585           else
8586             ++bp;
8587           break;
8588         }
8589     }
8590
8591   if ((bp1 != bp) && *bp1)
8592     pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8593
8594   Safe_free (buffer);
8595
8596   _G.inLine -= (!options.asmpeep);
8597 }
8598
8599 /*-----------------------------------------------------------------*/
8600 /* genRRC - rotate right with carry                                */
8601 /*-----------------------------------------------------------------*/
8602 static void genRRC (iCode *ic)
8603 {
8604   operand *left , *result ;
8605   int size, offset = 0, same;
8606
8607   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8608
8609   /* rotate right with carry */
8610   left = IC_LEFT(ic);
8611   result=IC_RESULT(ic);
8612   pic16_aopOp (left,ic,FALSE);
8613   pic16_aopOp (result,ic,TRUE);
8614
8615   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8616
8617   same = pic16_sameRegs(AOP(result),AOP(left));
8618
8619   size = AOP_SIZE(result);    
8620
8621   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8622
8623   /* get the lsb and put it into the carry */
8624   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8625
8626   offset = 0 ;
8627
8628   while(size--) {
8629
8630     if(same) {
8631       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8632     } else {
8633       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8634       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8635     }
8636
8637     offset++;
8638   }
8639
8640   pic16_freeAsmop(left,NULL,ic,TRUE);
8641   pic16_freeAsmop(result,NULL,ic,TRUE);
8642 }
8643
8644 /*-----------------------------------------------------------------*/
8645 /* genRLC - generate code for rotate left with carry               */
8646 /*-----------------------------------------------------------------*/
8647 static void genRLC (iCode *ic)
8648 {    
8649   operand *left , *result ;
8650   int size, offset = 0;
8651   int same;
8652
8653   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8654   /* rotate right with carry */
8655   left = IC_LEFT(ic);
8656   result=IC_RESULT(ic);
8657   pic16_aopOp (left,ic,FALSE);
8658   pic16_aopOp (result,ic,TRUE);
8659
8660   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8661
8662   same = pic16_sameRegs(AOP(result),AOP(left));
8663
8664   /* move it to the result */
8665   size = AOP_SIZE(result);    
8666
8667   /* get the msb and put it into the carry */
8668   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8669
8670   offset = 0 ;
8671
8672   while(size--) {
8673
8674     if(same) {
8675       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8676     } else {
8677       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8678       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8679     }
8680
8681     offset++;
8682   }
8683
8684
8685   pic16_freeAsmop(left,NULL,ic,TRUE);
8686   pic16_freeAsmop(result,NULL,ic,TRUE);
8687 }
8688
8689
8690 /* gpasm can get the highest order bit with HIGH/UPPER
8691  * so the following probably is not needed -- VR */
8692  
8693 /*-----------------------------------------------------------------*/
8694 /* genGetHbit - generates code get highest order bit               */
8695 /*-----------------------------------------------------------------*/
8696 static void genGetHbit (iCode *ic)
8697 {
8698     operand *left, *result;
8699     left = IC_LEFT(ic);
8700     result=IC_RESULT(ic);
8701     pic16_aopOp (left,ic,FALSE);
8702     pic16_aopOp (result,ic,FALSE);
8703
8704     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8705     /* get the highest order byte into a */
8706     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8707     if(AOP_TYPE(result) == AOP_CRY){
8708         pic16_emitcode("rlc","a");
8709         pic16_outBitC(result);
8710     }
8711     else{
8712         pic16_emitcode("rl","a");
8713         pic16_emitcode("anl","a,#0x01");
8714         pic16_outAcc(result);
8715     }
8716
8717
8718     pic16_freeAsmop(left,NULL,ic,TRUE);
8719     pic16_freeAsmop(result,NULL,ic,TRUE);
8720 }
8721
8722 #if 0
8723 /*-----------------------------------------------------------------*/
8724 /* AccRol - rotate left accumulator by known count                 */
8725 /*-----------------------------------------------------------------*/
8726 static void AccRol (int shCount)
8727 {
8728     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8729     shCount &= 0x0007;              // shCount : 0..7
8730     switch(shCount){
8731         case 0 :
8732             break;
8733         case 1 :
8734             pic16_emitcode("rl","a");
8735             break;
8736         case 2 :
8737             pic16_emitcode("rl","a");
8738             pic16_emitcode("rl","a");
8739             break;
8740         case 3 :
8741             pic16_emitcode("swap","a");
8742             pic16_emitcode("rr","a");
8743             break;
8744         case 4 :
8745             pic16_emitcode("swap","a");
8746             break;
8747         case 5 :
8748             pic16_emitcode("swap","a");
8749             pic16_emitcode("rl","a");
8750             break;
8751         case 6 :
8752             pic16_emitcode("rr","a");
8753             pic16_emitcode("rr","a");
8754             break;
8755         case 7 :
8756             pic16_emitcode("rr","a");
8757             break;
8758     }
8759 }
8760 #endif
8761
8762 /*-----------------------------------------------------------------*/
8763 /* AccLsh - left shift accumulator by known count                  */
8764 /*-----------------------------------------------------------------*/
8765 static void AccLsh (int shCount, int doMask)
8766 {
8767         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8768         switch(shCount){
8769                 case 0 :
8770                         return;
8771                         break;
8772                 case 1 :
8773                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8774                         break;
8775                 case 2 :
8776                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8777                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8778                         break;
8779                 case 3 :
8780                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8781                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8782                         break;
8783                 case 4 :
8784                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8785                         break;
8786                 case 5 :
8787                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8788                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8789                         break;
8790                 case 6 :
8791                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8792                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8793                         break;
8794                 case 7 :
8795                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8796                         break;
8797         }
8798         if (doMask) {
8799                 /* no masking is required in genPackBits */
8800                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8801         }
8802 }
8803
8804 /*-----------------------------------------------------------------*/
8805 /* AccRsh - right shift accumulator by known count                 */
8806 /*-----------------------------------------------------------------*/
8807 static void AccRsh (int shCount, int andmask)
8808 {
8809         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8810         switch(shCount){
8811                 case 0 :
8812                         return; break;
8813                 case 1 :
8814                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8815                         break;
8816                 case 2 :
8817                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8818                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8819                         break;
8820                 case 3 :
8821                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8822                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8823                         break;
8824                 case 4 :
8825                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8826                         break;
8827                 case 5 :
8828                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8829                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8830                         break;
8831                 case 6 :
8832                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8833                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8834                         break;
8835                 case 7 :
8836                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8837                         break;
8838         }
8839         
8840         if(andmask)
8841                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8842         else
8843                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8844 }
8845
8846 #if 0
8847 /*-----------------------------------------------------------------*/
8848 /* AccSRsh - signed right shift accumulator by known count                 */
8849 /*-----------------------------------------------------------------*/
8850 static void AccSRsh (int shCount)
8851 {
8852     symbol *tlbl ;
8853     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8854     if(shCount != 0){
8855         if(shCount == 1){
8856             pic16_emitcode("mov","c,acc.7");
8857             pic16_emitcode("rrc","a");
8858         } else if(shCount == 2){
8859             pic16_emitcode("mov","c,acc.7");
8860             pic16_emitcode("rrc","a");
8861             pic16_emitcode("mov","c,acc.7");
8862             pic16_emitcode("rrc","a");
8863         } else {
8864             tlbl = newiTempLabel(NULL);
8865             /* rotate right accumulator */
8866             AccRol(8 - shCount);
8867             /* and kill the higher order bits */
8868             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8869             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8870             pic16_emitcode("orl","a,#0x%02x",
8871                      (unsigned char)~SRMask[shCount]);
8872             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8873         }
8874     }
8875 }
8876 #endif
8877
8878 /*-----------------------------------------------------------------*/
8879 /* shiftR1Left2Result - shift right one byte from left to result   */
8880 /*-----------------------------------------------------------------*/
8881 static void shiftR1Left2ResultSigned (operand *left, int offl,
8882                                 operand *result, int offr,
8883                                 int shCount)
8884 {
8885   int same;
8886
8887   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8888
8889   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8890
8891   switch(shCount) {
8892   case 1:
8893     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8894     if(same) 
8895       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8896     else {
8897       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8898       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8899     }
8900
8901     break;
8902   case 2:
8903
8904     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8905     if(same) 
8906       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8907     else {
8908       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8909       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8910     }
8911     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8912     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8913
8914     break;
8915
8916   case 3:
8917     if(same)
8918       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8919     else {
8920       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8921       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8922     }
8923
8924     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8925     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8926     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8927
8928     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8929     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8930
8931     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8932     break;
8933
8934   case 4:
8935     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8936     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8937     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8938     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8939     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8940     break;
8941   case 5:
8942     if(same) {
8943       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8944     } else {
8945       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8946       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8947     }
8948     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8949     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8950     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8951     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8952     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8953     break;
8954
8955   case 6:
8956     if(same) {
8957       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8958       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8959       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8960       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8961       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8962       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8963     } else {
8964       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8965       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8966       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8967       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8968       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8969     }
8970     break;
8971
8972   case 7:
8973     if(same) {
8974       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8975       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8976       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8977       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8978     } else {
8979       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8980       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8981       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8982     }
8983
8984   default:
8985     break;
8986   }
8987 }
8988
8989 /*-----------------------------------------------------------------*/
8990 /* shiftR1Left2Result - shift right one byte from left to result   */
8991 /*-----------------------------------------------------------------*/
8992 static void shiftR1Left2Result (operand *left, int offl,
8993                                 operand *result, int offr,
8994                                 int shCount, int sign)
8995 {
8996   int same;
8997
8998   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8999
9000   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
9001
9002   /* Copy the msb into the carry if signed. */
9003   if(sign) {
9004     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
9005     return;
9006   }
9007
9008
9009
9010   switch(shCount) {
9011   case 1:
9012     emitCLRC;
9013     if(same) 
9014       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9015     else {
9016       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9017       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9018     }
9019     break;
9020   case 2:
9021     emitCLRC;
9022     if(same) {
9023       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9024     } else {
9025       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9026       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027     }
9028     emitCLRC;
9029     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9030
9031     break;
9032   case 3:
9033     if(same)
9034       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9035     else {
9036       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9037       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9038     }
9039
9040     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
9041     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
9042     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
9043     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9044     break;
9045       
9046   case 4:
9047     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9048     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9049     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9050     break;
9051
9052   case 5:
9053     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
9054     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
9055     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9056     //emitCLRC;
9057     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
9058
9059     break;
9060   case 6:
9061
9062     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
9063     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
9064     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9065     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
9066     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
9067     break;
9068
9069   case 7:
9070
9071     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9072     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9073     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9074
9075     break;
9076
9077   default:
9078     break;
9079   }
9080 }
9081
9082 /*-----------------------------------------------------------------*/
9083 /* shiftL1Left2Result - shift left one byte from left to result    */
9084 /*-----------------------------------------------------------------*/
9085 static void shiftL1Left2Result (operand *left, int offl,
9086                                 operand *result, int offr, int shCount)
9087 {
9088   int same;
9089
9090   //    char *l;
9091   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9092
9093   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
9094   DEBUGpic16_emitcode ("; ***","same =  %d",same);
9095     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9096     //    MOVA(l);
9097     /* shift left accumulator */
9098     //AccLsh(shCount, 1); // don't comment out just yet...
9099   //    pic16_aopPut(AOP(result),"a",offr);
9100
9101   switch(shCount) {
9102   case 1:
9103     /* Shift left 1 bit position */
9104     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9105     if(same) {
9106       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
9107     } else {
9108       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
9109       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9110     }
9111     break;
9112   case 2:
9113     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9114     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
9115     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9116     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9117     break;
9118   case 3:
9119     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9120     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
9121     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9122     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9123     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9124     break;
9125   case 4:
9126     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9127     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9128     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9129     break;
9130   case 5:
9131     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9132     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9133     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9134     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9135     break;
9136   case 6:
9137     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9138     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
9139     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9140     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9141     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9142     break;
9143   case 7:
9144     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9145     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9146     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9147     break;
9148
9149   default:
9150     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
9151   }
9152
9153 }
9154
9155 /*-----------------------------------------------------------------*/
9156 /* movLeft2Result - move byte from left to result                  */
9157 /*-----------------------------------------------------------------*/
9158 static void movLeft2Result (operand *left, int offl,
9159                             operand *result, int offr)
9160 {
9161   char *l;
9162   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9163   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
9164     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
9165
9166     if (*l == '@' && (IS_AOP_PREG(result))) {
9167       pic16_emitcode("mov","a,%s",l);
9168       pic16_aopPut(AOP(result),"a",offr);
9169     } else {
9170       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9171       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9172     }
9173   }
9174 }
9175
9176 /*-----------------------------------------------------------------*/
9177 /* shiftL2Left2Result - shift left two bytes from left to result   */
9178 /*-----------------------------------------------------------------*/
9179 static void shiftL2Left2Result (operand *left, int offl,
9180                                 operand *result, int offr, int shCount)
9181 {
9182   int same = pic16_sameRegs(AOP(result), AOP(left));
9183   int i;
9184
9185   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
9186
9187   if (same && (offl != offr)) { // shift bytes
9188     if (offr > offl) {
9189        for(i=1;i>-1;i--) {
9190          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9191          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9192        }
9193     } else { // just treat as different later on
9194                 same = 0;
9195     }
9196   }
9197
9198   if(same) {
9199     switch(shCount) {
9200     case 0:
9201       break;
9202     case 1:
9203     case 2:
9204     case 3:
9205
9206       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
9207       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
9208       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9209
9210       while(--shCount) {
9211                 emitCLRC;
9212                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9213                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9214       }
9215
9216       break;
9217     case 4:
9218     case 5:
9219       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
9220       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
9221       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9222       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9223       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
9224       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9225       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9226       if(shCount >=5) {
9227                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9228                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9229       }
9230       break;
9231     case 6:
9232       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9233       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9234       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9235       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9236       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9237       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9238       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9239       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9240       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9241       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9242       break;
9243     case 7:
9244       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9245       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
9246       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9247       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9248       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9249     }
9250
9251   } else {
9252     switch(shCount) {
9253     case 0:
9254       break;
9255     case 1:
9256     case 2:
9257     case 3:
9258       /* note, use a mov/add for the shift since the mov has a
9259          chance of getting optimized out */
9260       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9261       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9262       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9263       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9264       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9265
9266       while(--shCount) {
9267                 emitCLRC;
9268                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9269                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9270       }
9271       break;
9272
9273     case 4:
9274     case 5:
9275       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9276       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9277       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9278       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9279       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9280       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9281       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9282       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9283
9284
9285       if(shCount == 5) {
9286                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9287                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9288       }
9289       break;
9290     case 6:
9291       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9292       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9293       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9294       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9295
9296       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9297       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9298       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9299       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9300       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9301       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9302       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9303       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9304       break;
9305     case 7:
9306       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9307       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9308       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9309       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9310       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9311     }
9312   }
9313
9314 }
9315 /*-----------------------------------------------------------------*/
9316 /* shiftR2Left2Result - shift right two bytes from left to result  */
9317 /*-----------------------------------------------------------------*/
9318 static void shiftR2Left2Result (operand *left, int offl,
9319                                 operand *result, int offr,
9320                                 int shCount, int sign)
9321 {
9322   int same = pic16_sameRegs(AOP(result), AOP(left));
9323   int i;
9324   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9325
9326   if (same && (offl != offr)) { // shift right bytes
9327     if (offr < offl) {
9328        for(i=0;i<2;i++) {
9329          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9330          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9331        }
9332     } else { // just treat as different later on
9333                 same = 0;
9334     }
9335   }
9336
9337   switch(shCount) {
9338   case 0:
9339     break;
9340   case 1:
9341   case 2:
9342   case 3:
9343     /* obtain sign from left operand */
9344     if(sign)
9345       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16));
9346     else
9347       emitCLRC;
9348
9349     if(same) {
9350       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9351       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9352     } else {
9353       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9354       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9355       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9356       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9357     }
9358
9359     while(--shCount) {
9360       if(sign)
9361         /* now get sign from already assigned result (avoid BANKSEL) */
9362         pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9363       else
9364         emitCLRC;
9365       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9366       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9367     }
9368     break;
9369   case 4:
9370   case 5:
9371     if(same) {
9372
9373       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9374       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9375       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9376
9377       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9378       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9379       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9380       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9381     } else {
9382       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9383       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9384       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9385
9386       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9387       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9388       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9389       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9390       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9391     }
9392
9393     if(shCount >=5) {
9394       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9395       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9396     }
9397
9398     if(sign) {
9399       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9400       pic16_emitpcode(POC_BTFSC, 
9401                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9402       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9403     }
9404
9405     break;
9406
9407   case 6:
9408     if(same) {
9409
9410       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9411       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9412
9413       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9414       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9415       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9416       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9417       if(sign) {
9418         pic16_emitpcode(POC_BTFSC, 
9419                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9420         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9421       }
9422       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9423       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9424       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9425       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9426     } else {
9427       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9428       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9429       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9430       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9431       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9432       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9433       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9434       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9435       if(sign) {
9436         pic16_emitpcode(POC_BTFSC, 
9437                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9438         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9439       }
9440       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9441       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9442
9443         
9444     }
9445
9446     break;
9447   case 7:
9448     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9449     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9450     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9451     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9452     if(sign) {
9453       emitSKPNC;
9454       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9455     } else 
9456       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9457   }
9458 }
9459
9460
9461 /*-----------------------------------------------------------------*/
9462 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9463 /*-----------------------------------------------------------------*/
9464 static void shiftLLeftOrResult (operand *left, int offl,
9465                                 operand *result, int offr, int shCount)
9466 {
9467     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9468
9469     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9470     /* shift left accumulator */
9471     AccLsh(shCount, 1);
9472     /* or with result */
9473     /* back to result */
9474     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9475 }
9476
9477 /*-----------------------------------------------------------------*/
9478 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9479 /*-----------------------------------------------------------------*/
9480 static void shiftRLeftOrResult (operand *left, int offl,
9481                                 operand *result, int offr, int shCount)
9482 {
9483     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9484     
9485     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9486     /* shift right accumulator */
9487     AccRsh(shCount, 1);
9488     /* or with result */
9489     /* back to result */
9490     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9491 }
9492
9493 /*-----------------------------------------------------------------*/
9494 /* genlshOne - left shift a one byte quantity by known count       */
9495 /*-----------------------------------------------------------------*/
9496 static void genlshOne (operand *result, operand *left, int shCount)
9497 {       
9498     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9499     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9500 }
9501
9502 /*-----------------------------------------------------------------*/
9503 /* genlshTwo - left shift two bytes by known amount != 0           */
9504 /*-----------------------------------------------------------------*/
9505 static void genlshTwo (operand *result,operand *left, int shCount)
9506 {
9507     int size;
9508     
9509     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9510     size = pic16_getDataSize(result);
9511
9512     /* if shCount >= 8 */
9513     if (shCount >= 8) {
9514         shCount -= 8 ;
9515
9516         if (size > 1){
9517             if (shCount)
9518                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9519             else 
9520                 movLeft2Result(left, LSB, result, MSB16);
9521         }
9522         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9523     }
9524
9525     /*  1 <= shCount <= 7 */
9526     else {  
9527         if(size == 1)
9528             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9529         else 
9530             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9531     }
9532 }
9533
9534 /*-----------------------------------------------------------------*/
9535 /* shiftLLong - shift left one long from left to result            */
9536 /* offr = LSB or MSB16                                             */
9537 /*-----------------------------------------------------------------*/
9538 static void shiftLLong (operand *left, operand *result, int offr )
9539 {
9540     int size = AOP_SIZE(result);
9541     int same = pic16_sameRegs(AOP(left),AOP(result));
9542         int i;
9543
9544     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9545
9546         if (same && (offr == MSB16)) { //shift one byte
9547                 for(i=size-1;i>=MSB16;i--) {
9548                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9549                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9550                 }
9551         } else {
9552                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9553         }
9554         
9555     if (size > LSB+offr ){
9556                 if (same) {
9557                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9558                 } else {
9559                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9560                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9561                 }
9562          }
9563
9564     if(size > MSB16+offr){
9565                 if (same) {
9566                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9567                 } else {
9568                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9569                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9570                 }
9571     }
9572
9573     if(size > MSB24+offr){
9574                 if (same) {
9575                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9576                 } else {
9577                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9578                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9579                 }
9580     }
9581
9582     if(size > MSB32+offr){
9583                 if (same) {
9584                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9585                 } else {
9586                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9587                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9588                 }
9589     }
9590     if(offr != LSB)
9591                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9592
9593 }
9594
9595 /*-----------------------------------------------------------------*/
9596 /* genlshFour - shift four byte by a known amount != 0             */
9597 /*-----------------------------------------------------------------*/
9598 static void genlshFour (operand *result, operand *left, int shCount)
9599 {
9600     int size;
9601
9602     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9603     size = AOP_SIZE(result);
9604
9605     /* if shifting more that 3 bytes */
9606     if (shCount >= 24 ) {
9607         shCount -= 24;
9608         if (shCount)
9609             /* lowest order of left goes to the highest
9610             order of the destination */
9611             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9612         else
9613             movLeft2Result(left, LSB, result, MSB32);
9614
9615                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9616                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9617                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9618
9619         return;
9620     }
9621
9622     /* more than two bytes */
9623     else if ( shCount >= 16 ) {
9624         /* lower order two bytes goes to higher order two bytes */
9625         shCount -= 16;
9626         /* if some more remaining */
9627         if (shCount)
9628             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9629         else {
9630             movLeft2Result(left, MSB16, result, MSB32);
9631             movLeft2Result(left, LSB, result, MSB24);
9632         }
9633                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9634                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9635         return;
9636     }    
9637
9638     /* if more than 1 byte */
9639     else if ( shCount >= 8 ) {
9640         /* lower order three bytes goes to higher order  three bytes */
9641         shCount -= 8;
9642         if(size == 2){
9643             if(shCount)
9644                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9645             else
9646                 movLeft2Result(left, LSB, result, MSB16);
9647         }
9648         else{   /* size = 4 */
9649             if(shCount == 0){
9650                 movLeft2Result(left, MSB24, result, MSB32);
9651                 movLeft2Result(left, MSB16, result, MSB24);
9652                 movLeft2Result(left, LSB, result, MSB16);
9653                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9654             }
9655             else if(shCount == 1)
9656                 shiftLLong(left, result, MSB16);
9657             else{
9658                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9659                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9660                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9661                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9662             }
9663         }
9664     }
9665
9666     /* 1 <= shCount <= 7 */
9667     else if(shCount <= 3)
9668     { 
9669         shiftLLong(left, result, LSB);
9670         while(--shCount >= 1)
9671             shiftLLong(result, result, LSB);
9672     }
9673     /* 3 <= shCount <= 7, optimize */
9674     else{
9675         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9676         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9677         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9678     }
9679 }
9680
9681 /*-----------------------------------------------------------------*/
9682 /* genLeftShiftLiteral - left shifting by known count              */
9683 /*-----------------------------------------------------------------*/
9684 void pic16_genLeftShiftLiteral (operand *left,
9685                                  operand *right,
9686                                  operand *result,
9687                                  iCode *ic)
9688 {    
9689     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9690     int size;
9691
9692     FENTRY;
9693     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9694     pic16_freeAsmop(right,NULL,ic,TRUE);
9695
9696     pic16_aopOp(left,ic,FALSE);
9697     pic16_aopOp(result,ic,TRUE);
9698
9699     size = getSize(operandType(result));
9700
9701 #if VIEW_SIZE
9702     pic16_emitcode("; shift left ","result %d, left %d",size,
9703              AOP_SIZE(left));
9704 #endif
9705
9706     /* I suppose that the left size >= result size */
9707     if(shCount == 0){
9708         while(size--){
9709             movLeft2Result(left, size, result, size);
9710         }
9711     }
9712
9713     else if(shCount >= (size * 8))
9714         while(size--)
9715             pic16_aopPut(AOP(result),zero,size);
9716     else{
9717         switch (size) {
9718             case 1:
9719                 genlshOne (result,left,shCount);
9720                 break;
9721
9722             case 2:
9723             case 3:
9724                 genlshTwo (result,left,shCount);
9725                 break;
9726
9727             case 4:
9728                 genlshFour (result,left,shCount);
9729                 break;
9730         }
9731     }
9732     pic16_freeAsmop(left,NULL,ic,TRUE);
9733     pic16_freeAsmop(result,NULL,ic,TRUE);
9734 }
9735
9736 /*-----------------------------------------------------------------*
9737  * genMultiAsm - repeat assembly instruction for size of register.
9738  * if endian == 1, then the high byte (i.e base address + size of 
9739  * register) is used first else the low byte is used first;
9740  *-----------------------------------------------------------------*/
9741 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9742 {
9743
9744   int offset = 0;
9745
9746   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9747
9748   if(!reg)
9749     return;
9750
9751   if(!endian) {
9752     endian = 1;
9753   } else {
9754     endian = -1;
9755     offset = size-1;
9756   }
9757
9758   while(size--) {
9759     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9760     offset += endian;
9761   }
9762
9763 }
9764
9765 #if !(USE_GENERIC_SIGNED_SHIFT)
9766 /*-----------------------------------------------------------------*/
9767 /* genLeftShift - generates code for left shifting                 */
9768 /*-----------------------------------------------------------------*/
9769 static void genLeftShift (iCode *ic)
9770 {
9771   operand *left,*right, *result;
9772   int size, offset;
9773 //  char *l;
9774   symbol *tlbl , *tlbl1;
9775   pCodeOp *pctemp;
9776
9777   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9778
9779   right = IC_RIGHT(ic);
9780   left  = IC_LEFT(ic);
9781   result = IC_RESULT(ic);
9782
9783   pic16_aopOp(right,ic,FALSE);
9784
9785   /* if the shift count is known then do it 
9786      as efficiently as possible */
9787   if (AOP_TYPE(right) == AOP_LIT) {
9788     pic16_genLeftShiftLiteral (left,right,result,ic);
9789     return ;
9790   }
9791
9792   /* shift count is unknown then we have to form
9793    * a loop. Get the loop count in WREG : Note: we take
9794    * only the lower order byte since shifting
9795    * more than 32 bits make no sense anyway, ( the
9796    * largest size of an object can be only 32 bits ) */
9797   
9798   pic16_aopOp(left,ic,FALSE);
9799   pic16_aopOp(result,ic,FALSE);
9800
9801   /* now move the left to the result if they are not the
9802    * same, and if size > 1,
9803    * and if right is not same to result (!!!) -- VR */
9804   if (!pic16_sameRegs(AOP(left),AOP(result))
9805       && (AOP_SIZE(result) > 1)) {
9806
9807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9808
9809     size = AOP_SIZE(result);
9810     offset=0;
9811     while (size--) {
9812
9813 #if 0
9814       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9815       if (*l == '@' && (IS_AOP_PREG(result))) {
9816
9817           pic16_emitcode("mov","a,%s",l);
9818           pic16_aopPut(AOP(result),"a",offset);
9819       } else
9820 #endif
9821       {
9822         /* we don't know if left is a literal or a register, take care -- VR */
9823         pic16_mov2f(AOP(result), AOP(left), offset);
9824       }
9825       offset++;
9826     }
9827   }
9828
9829   size = AOP_SIZE(result);
9830
9831   /* if it is only one byte then */
9832   if (size == 1) {
9833     if(optimized_for_speed) {
9834       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9835       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9836       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9837       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9838       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9839       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9840       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9841       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9842       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9843       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9844       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9845       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9846     } else {
9847
9848       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9849
9850       tlbl = newiTempLabel(NULL);
9851
9852 #if 1
9853       /* this is already done, why change it? */
9854       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9855                 pic16_mov2f(AOP(result), AOP(left), 0);
9856       }
9857 #endif
9858
9859       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9860       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9861       pic16_emitpLabel(tlbl->key);
9862       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9863       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9864       emitSKPC;
9865       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9866     }
9867     goto release ;
9868   }
9869     
9870   if (pic16_sameRegs(AOP(left),AOP(result))) {
9871
9872     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9873     
9874     tlbl = newiTempLabel(NULL);
9875     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9876     genMultiAsm(POC_RRCF, result, size,1);
9877     pic16_emitpLabel(tlbl->key);
9878     genMultiAsm(POC_RLCF, result, size,0);
9879     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9880     emitSKPC;
9881     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9882     goto release;
9883   }
9884
9885   //tlbl = newiTempLabel(NULL);
9886   //offset = 0 ;   
9887   //tlbl1 = newiTempLabel(NULL);
9888
9889   //reAdjustPreg(AOP(result));    
9890     
9891   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9892   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9893   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9894   //MOVA(l);
9895   //pic16_emitcode("add","a,acc");         
9896   //pic16_aopPut(AOP(result),"a",offset++);
9897   //while (--size) {
9898   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9899   //  MOVA(l);
9900   //  pic16_emitcode("rlc","a");         
9901   //  pic16_aopPut(AOP(result),"a",offset++);
9902   //}
9903   //reAdjustPreg(AOP(result));
9904
9905   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9906   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9907
9908
9909   tlbl = newiTempLabel(NULL);
9910   tlbl1= newiTempLabel(NULL);
9911
9912   size = AOP_SIZE(result);
9913   offset = 1;
9914
9915   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9916
9917   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9918
9919   /* offset should be 0, 1 or 3 */
9920   
9921   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9922   emitSKPNZ;
9923   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9924
9925   pic16_emitpcode(POC_MOVWF, pctemp);
9926
9927
9928   pic16_emitpLabel(tlbl->key);
9929
9930   emitCLRC;
9931   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9932   while(--size)
9933     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9934
9935   pic16_emitpcode(POC_DECFSZ,  pctemp);
9936   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9937   pic16_emitpLabel(tlbl1->key);
9938
9939   pic16_popReleaseTempReg(pctemp,1);
9940
9941
9942  release:
9943   pic16_freeAsmop (right,NULL,ic,TRUE);
9944   pic16_freeAsmop(left,NULL,ic,TRUE);
9945   pic16_freeAsmop(result,NULL,ic,TRUE);
9946 }
9947 #endif
9948
9949
9950 #if 0
9951 #error old code (left here for reference)
9952 /*-----------------------------------------------------------------*/
9953 /* genLeftShift - generates code for left shifting                 */
9954 /*-----------------------------------------------------------------*/
9955 static void genLeftShift (iCode *ic)
9956 {
9957   operand *left,*right, *result;
9958   int size, offset;
9959   char *l;
9960   symbol *tlbl , *tlbl1;
9961   pCodeOp *pctemp;
9962
9963   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9964
9965   right = IC_RIGHT(ic);
9966   left  = IC_LEFT(ic);
9967   result = IC_RESULT(ic);
9968
9969   pic16_aopOp(right,ic,FALSE);
9970
9971   /* if the shift count is known then do it 
9972      as efficiently as possible */
9973   if (AOP_TYPE(right) == AOP_LIT) {
9974     pic16_genLeftShiftLiteral (left,right,result,ic);
9975     return ;
9976   }
9977
9978   /* shift count is unknown then we have to form 
9979      a loop get the loop count in B : Note: we take
9980      only the lower order byte since shifting
9981      more that 32 bits make no sense anyway, ( the
9982      largest size of an object can be only 32 bits ) */  
9983
9984     
9985   pic16_aopOp(left,ic,FALSE);
9986   pic16_aopOp(result,ic,FALSE);
9987
9988   /* now move the left to the result if they are not the
9989      same */
9990   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9991       AOP_SIZE(result) > 1) {
9992
9993     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9994
9995     size = AOP_SIZE(result);
9996     offset=0;
9997     while (size--) {
9998       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9999       if (*l == '@' && (IS_AOP_PREG(result))) {
10000
10001         pic16_emitcode("mov","a,%s",l);
10002         pic16_aopPut(AOP(result),"a",offset);
10003       } else {
10004
10005         /* we don't know if left is a literal or a register, take care -- VR */
10006         pic16_mov2f(AOP(result), AOP(left), offset);
10007       }
10008       offset++;
10009     }
10010   }
10011
10012   size = AOP_SIZE(result);
10013
10014   /* if it is only one byte then */
10015   if (size == 1) {
10016     if(optimized_for_speed) {
10017       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
10018       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
10019       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
10020       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10021       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10022       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
10023       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10024       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
10025       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
10026       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
10027       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
10028       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
10029     } else {
10030
10031       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10032
10033       tlbl = newiTempLabel(NULL);
10034       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10035                 pic16_mov2f(AOP(result), AOP(left), 0);
10036                 
10037 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10038 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10039       }
10040
10041       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10042       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10043       pic16_emitpLabel(tlbl->key);
10044       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10045       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10046       emitSKPC;
10047       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10048     }
10049     goto release ;
10050   }
10051     
10052   if (pic16_sameRegs(AOP(left),AOP(result))) {
10053
10054     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10055     
10056     tlbl = newiTempLabel(NULL);
10057     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10058     genMultiAsm(POC_RRCF, result, size,1);
10059     pic16_emitpLabel(tlbl->key);
10060     genMultiAsm(POC_RLCF, result, size,0);
10061     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10062     emitSKPC;
10063     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10064     goto release;
10065   }
10066
10067   //tlbl = newiTempLabel(NULL);
10068   //offset = 0 ;   
10069   //tlbl1 = newiTempLabel(NULL);
10070
10071   //reAdjustPreg(AOP(result));    
10072     
10073   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
10074   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10075   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10076   //MOVA(l);
10077   //pic16_emitcode("add","a,acc");         
10078   //pic16_aopPut(AOP(result),"a",offset++);
10079   //while (--size) {
10080   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10081   //  MOVA(l);
10082   //  pic16_emitcode("rlc","a");         
10083   //  pic16_aopPut(AOP(result),"a",offset++);
10084   //}
10085   //reAdjustPreg(AOP(result));
10086
10087   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10088   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10089
10090
10091   tlbl = newiTempLabel(NULL);
10092   tlbl1= newiTempLabel(NULL);
10093
10094   size = AOP_SIZE(result);
10095   offset = 1;
10096
10097   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10098
10099   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10100
10101   /* offset should be 0, 1 or 3 */
10102   
10103   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
10104   emitSKPNZ;
10105   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10106
10107   pic16_emitpcode(POC_MOVWF, pctemp);
10108
10109
10110   pic16_emitpLabel(tlbl->key);
10111
10112   emitCLRC;
10113   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
10114   while(--size)
10115     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
10116
10117   pic16_emitpcode(POC_DECFSZ,  pctemp);
10118   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10119   pic16_emitpLabel(tlbl1->key);
10120
10121   pic16_popReleaseTempReg(pctemp,1);
10122
10123
10124  release:
10125   pic16_freeAsmop (right,NULL,ic,TRUE);
10126   pic16_freeAsmop(left,NULL,ic,TRUE);
10127   pic16_freeAsmop(result,NULL,ic,TRUE);
10128 }
10129 #endif
10130
10131 /*-----------------------------------------------------------------*/
10132 /* genrshOne - right shift a one byte quantity by known count      */
10133 /*-----------------------------------------------------------------*/
10134 static void genrshOne (operand *result, operand *left,
10135                        int shCount, int sign)
10136 {
10137     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10138     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
10139 }
10140
10141 /*-----------------------------------------------------------------*/
10142 /* genrshTwo - right shift two bytes by known amount != 0          */
10143 /*-----------------------------------------------------------------*/
10144 static void genrshTwo (operand *result,operand *left,
10145                        int shCount, int sign)
10146 {
10147   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
10148   /* if shCount >= 8 */
10149   if (shCount >= 8) {
10150     shCount -= 8 ;
10151     if (shCount)
10152       shiftR1Left2Result(left, MSB16, result, LSB,
10153                          shCount, sign);
10154     else
10155       movLeft2Result(left, MSB16, result, LSB);
10156
10157     pic16_addSign (result, 1, sign);
10158   }
10159
10160   /*  1 <= shCount <= 7 */
10161   else
10162     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
10163 }
10164
10165 /*-----------------------------------------------------------------*/
10166 /* shiftRLong - shift right one long from left to result           */
10167 /* offl = LSB or MSB16                                             */
10168 /*-----------------------------------------------------------------*/
10169 static void shiftRLong (operand *left, int offl,
10170                         operand *result, int sign)
10171 {
10172     int size = AOP_SIZE(result);
10173     int same = pic16_sameRegs(AOP(left),AOP(result));
10174     int i;
10175     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
10176
10177         if (same && (offl == MSB16)) { //shift one byte right
10178                 for(i=MSB16;i<size;i++) {
10179                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
10180                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
10181                 }
10182         }
10183
10184     if(sign)
10185                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
10186         else
10187                 emitCLRC;
10188
10189         if (same) {
10190                 if (offl == LSB)
10191                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
10192         } else {
10193         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
10194         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
10195         }
10196
10197     if(offl == MSB16) {
10198         /* add sign of "a" */
10199         pic16_addSign(result, MSB32, sign);
10200         }
10201
10202         if (same) {
10203         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
10204         } else {
10205         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
10206         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
10207         }
10208         
10209         if (same) {
10210         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
10211         } else {
10212         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
10213         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
10214         }
10215
10216         if (same) {
10217         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
10218         } else {
10219         if(offl == LSB){
10220                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
10221                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
10222         }
10223         }
10224 }
10225
10226 /*-----------------------------------------------------------------*/
10227 /* genrshFour - shift four byte by a known amount != 0             */
10228 /*-----------------------------------------------------------------*/
10229 static void genrshFour (operand *result, operand *left,
10230                         int shCount, int sign)
10231 {
10232   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10233   /* if shifting more that 3 bytes */
10234   if(shCount >= 24 ) {
10235     shCount -= 24;
10236     if(shCount)
10237       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
10238     else
10239       movLeft2Result(left, MSB32, result, LSB);
10240
10241     pic16_addSign(result, MSB16, sign);
10242   }
10243   else if(shCount >= 16){
10244     shCount -= 16;
10245     if(shCount)
10246       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
10247     else{
10248       movLeft2Result(left, MSB24, result, LSB);
10249       movLeft2Result(left, MSB32, result, MSB16);
10250     }
10251     pic16_addSign(result, MSB24, sign);
10252   }
10253   else if(shCount >= 8){
10254     shCount -= 8;
10255     if(shCount == 1)
10256       shiftRLong(left, MSB16, result, sign);
10257     else if(shCount == 0){
10258       movLeft2Result(left, MSB16, result, LSB);
10259       movLeft2Result(left, MSB24, result, MSB16);
10260       movLeft2Result(left, MSB32, result, MSB24);
10261       pic16_addSign(result, MSB32, sign);
10262     }
10263     else{ //shcount >= 2
10264       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10265       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10266       /* the last shift is signed */
10267       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10268       pic16_addSign(result, MSB32, sign);
10269     }
10270   }
10271   else{   /* 1 <= shCount <= 7 */
10272     if(shCount <= 2){
10273       shiftRLong(left, LSB, result, sign);
10274       if(shCount == 2)
10275         shiftRLong(result, LSB, result, sign);
10276     }
10277     else{
10278       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10279       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10280       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10281     }
10282   }
10283 }
10284
10285 /*-----------------------------------------------------------------*/
10286 /* genRightShiftLiteral - right shifting by known count            */
10287 /*-----------------------------------------------------------------*/
10288 static void genRightShiftLiteral (operand *left,
10289                                   operand *right,
10290                                   operand *result,
10291                                   iCode *ic,
10292                                   int sign)
10293 {    
10294   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10295   int lsize,res_size;
10296
10297   pic16_freeAsmop(right,NULL,ic,TRUE);
10298
10299   pic16_aopOp(left,ic,FALSE);
10300   pic16_aopOp(result,ic,TRUE);
10301
10302   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10303
10304 #if VIEW_SIZE
10305   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10306                  AOP_SIZE(left));
10307 #endif
10308
10309   lsize = pic16_getDataSize(left);
10310   res_size = pic16_getDataSize(result);
10311   /* test the LEFT size !!! */
10312
10313   /* I suppose that the left size >= result size */
10314   if(shCount == 0){
10315     assert (res_size <= lsize);
10316     while (res_size--) {
10317       pic16_mov2f (AOP(result), AOP(left), res_size);
10318     } // for
10319   }
10320
10321   else if(shCount >= (lsize * 8)){
10322
10323     if(res_size == 1) {
10324       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10325       if(sign) {
10326         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10327         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10328       }
10329     } else {
10330
10331       if(sign) {
10332         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10333         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10334         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10335         while(res_size--)
10336           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10337
10338       } else {
10339
10340         while(res_size--)
10341           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10342       }
10343     }
10344   } else {
10345
10346     switch (res_size) {
10347     case 1:
10348       genrshOne (result,left,shCount,sign);
10349       break;
10350
10351     case 2:
10352       genrshTwo (result,left,shCount,sign);
10353       break;
10354
10355     case 4:
10356       genrshFour (result,left,shCount,sign);
10357       break;
10358     default :
10359       break;
10360     }
10361
10362   }
10363
10364   pic16_freeAsmop(left,NULL,ic,TRUE);
10365   pic16_freeAsmop(result,NULL,ic,TRUE);
10366 }
10367
10368 #if !(USE_GENERIC_SIGNED_SHIFT)
10369 /*-----------------------------------------------------------------*/
10370 /* genSignedRightShift - right shift of signed number              */
10371 /*-----------------------------------------------------------------*/
10372 static void genSignedRightShift (iCode *ic)
10373 {
10374   operand *right, *left, *result;
10375   int size, offset;
10376   //  char *l;
10377   symbol *tlbl, *tlbl1 ;
10378   pCodeOp *pctemp;
10379
10380   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10381
10382   /* we do it the hard way put the shift count in b
10383      and loop thru preserving the sign */
10384   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10385
10386   right = IC_RIGHT(ic);
10387   left  = IC_LEFT(ic);
10388   result = IC_RESULT(ic);
10389
10390   pic16_aopOp(right,ic,FALSE);  
10391   pic16_aopOp(left,ic,FALSE);
10392   pic16_aopOp(result,ic,FALSE);
10393
10394
10395   if ( AOP_TYPE(right) == AOP_LIT) {
10396     genRightShiftLiteral (left,right,result,ic,1);
10397     return ;
10398   }
10399   /* shift count is unknown then we have to form 
10400      a loop get the loop count in B : Note: we take
10401      only the lower order byte since shifting
10402      more that 32 bits make no sense anyway, ( the
10403      largest size of an object can be only 32 bits ) */  
10404
10405   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10406   //pic16_emitcode("inc","b");
10407   //pic16_freeAsmop (right,NULL,ic,TRUE);
10408   //pic16_aopOp(left,ic,FALSE);
10409   //pic16_aopOp(result,ic,FALSE);
10410
10411   /* now move the left to the result if they are not the
10412      same */
10413   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10414       AOP_SIZE(result) > 1) {
10415
10416     size = AOP_SIZE(result);
10417     offset=0;
10418     while (size--) { 
10419       /*
10420         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10421         if (*l == '@' && IS_AOP_PREG(result)) {
10422
10423         pic16_emitcode("mov","a,%s",l);
10424         pic16_aopPut(AOP(result),"a",offset);
10425         } else
10426         pic16_aopPut(AOP(result),l,offset);
10427       */
10428       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10429       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10430
10431       offset++;
10432     }
10433   }
10434
10435   /* mov the highest order bit to OVR */    
10436   tlbl = newiTempLabel(NULL);
10437   tlbl1= newiTempLabel(NULL);
10438
10439   size = AOP_SIZE(result);
10440   offset = size - 1;
10441
10442   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10443
10444   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10445
10446   /* offset should be 0, 1 or 3 */
10447   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10448   emitSKPNZ;
10449   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10450
10451   pic16_emitpcode(POC_MOVWF, pctemp);
10452
10453
10454   pic16_emitpLabel(tlbl->key);
10455
10456   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10457   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10458
10459   while(--size) {
10460     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10461   }
10462
10463   pic16_emitpcode(POC_DECFSZ,  pctemp);
10464   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10465   pic16_emitpLabel(tlbl1->key);
10466
10467   pic16_popReleaseTempReg(pctemp,1);
10468 #if 0
10469   size = AOP_SIZE(result);
10470   offset = size - 1;
10471   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10472   pic16_emitcode("rlc","a");
10473   pic16_emitcode("mov","ov,c");
10474   /* if it is only one byte then */
10475   if (size == 1) {
10476     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10477     MOVA(l);
10478     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10479     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10480     pic16_emitcode("mov","c,ov");
10481     pic16_emitcode("rrc","a");
10482     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10483     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10484     pic16_aopPut(AOP(result),"a",0);
10485     goto release ;
10486   }
10487
10488   reAdjustPreg(AOP(result));
10489   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10490   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10491   pic16_emitcode("mov","c,ov");
10492   while (size--) {
10493     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10494     MOVA(l);
10495     pic16_emitcode("rrc","a");         
10496     pic16_aopPut(AOP(result),"a",offset--);
10497   }
10498   reAdjustPreg(AOP(result));
10499   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10500   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10501
10502  release:
10503 #endif
10504
10505   pic16_freeAsmop(left,NULL,ic,TRUE);
10506   pic16_freeAsmop(result,NULL,ic,TRUE);
10507   pic16_freeAsmop(right,NULL,ic,TRUE);
10508 }
10509 #endif
10510
10511 #if !(USE_GENERIC_SIGNED_SHIFT)
10512 #warning This implementation of genRightShift() is incomplete!
10513 /*-----------------------------------------------------------------*/
10514 /* genRightShift - generate code for right shifting                */
10515 /*-----------------------------------------------------------------*/
10516 static void genRightShift (iCode *ic)
10517 {
10518     operand *right, *left, *result;
10519     sym_link *letype ;
10520     int size, offset;
10521     char *l;
10522     symbol *tlbl, *tlbl1 ;
10523
10524     /* if signed then we do it the hard way preserve the
10525     sign bit moving it inwards */
10526     letype = getSpec(operandType(IC_LEFT(ic)));
10527     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10528
10529     if (!SPEC_USIGN(letype)) {
10530         genSignedRightShift (ic);
10531         return ;
10532     }
10533
10534     /* signed & unsigned types are treated the same : i.e. the
10535     signed is NOT propagated inwards : quoting from the
10536     ANSI - standard : "for E1 >> E2, is equivalent to division
10537     by 2**E2 if unsigned or if it has a non-negative value,
10538     otherwise the result is implementation defined ", MY definition
10539     is that the sign does not get propagated */
10540
10541     right = IC_RIGHT(ic);
10542     left  = IC_LEFT(ic);
10543     result = IC_RESULT(ic);
10544
10545     pic16_aopOp(right,ic,FALSE);
10546
10547     /* if the shift count is known then do it 
10548     as efficiently as possible */
10549     if (AOP_TYPE(right) == AOP_LIT) {
10550         genRightShiftLiteral (left,right,result,ic, 0);
10551         return ;
10552     }
10553
10554     /* shift count is unknown then we have to form 
10555     a loop get the loop count in B : Note: we take
10556     only the lower order byte since shifting
10557     more that 32 bits make no sense anyway, ( the
10558     largest size of an object can be only 32 bits ) */  
10559
10560     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10561     pic16_emitcode("inc","b");
10562     pic16_aopOp(left,ic,FALSE);
10563     pic16_aopOp(result,ic,FALSE);
10564
10565     /* now move the left to the result if they are not the
10566     same */
10567     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10568         AOP_SIZE(result) > 1) {
10569
10570         size = AOP_SIZE(result);
10571         offset=0;
10572         while (size--) {
10573             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10574             if (*l == '@' && IS_AOP_PREG(result)) {
10575
10576                 pic16_emitcode("mov","a,%s",l);
10577                 pic16_aopPut(AOP(result),"a",offset);
10578             } else
10579                 pic16_aopPut(AOP(result),l,offset);
10580             offset++;
10581         }
10582     }
10583
10584     tlbl = newiTempLabel(NULL);
10585     tlbl1= newiTempLabel(NULL);
10586     size = AOP_SIZE(result);
10587     offset = size - 1;
10588
10589     /* if it is only one byte then */
10590     if (size == 1) {
10591
10592       tlbl = newiTempLabel(NULL);
10593       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10594         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10595         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10596       }
10597
10598       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10599       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10600       pic16_emitpLabel(tlbl->key);
10601       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10602       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10603       emitSKPC;
10604       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10605
10606       goto release ;
10607     }
10608
10609     reAdjustPreg(AOP(result));
10610     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10611     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10612     CLRC;
10613     while (size--) {
10614         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10615         MOVA(l);
10616         pic16_emitcode("rrc","a");         
10617         pic16_aopPut(AOP(result),"a",offset--);
10618     }
10619     reAdjustPreg(AOP(result));
10620
10621     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10622     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10623
10624 release:
10625     pic16_freeAsmop(left,NULL,ic,TRUE);
10626     pic16_freeAsmop (right,NULL,ic,TRUE);
10627     pic16_freeAsmop(result,NULL,ic,TRUE);
10628 }
10629 #endif
10630
10631 #if (USE_GENERIC_SIGNED_SHIFT)
10632 /*-----------------------------------------------------------------*/
10633 /* genGenericShift - generates code for left or right shifting     */
10634 /*-----------------------------------------------------------------*/
10635 static void genGenericShift (iCode *ic, int isShiftLeft) {
10636   operand *left,*right, *result;
10637   int offset;
10638   int sign, signedCount;
10639   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10640   PIC_OPCODE pos_shift, neg_shift;
10641
10642   FENTRY;
10643
10644   right = IC_RIGHT(ic);
10645   left  = IC_LEFT(ic);
10646   result = IC_RESULT(ic);
10647
10648   pic16_aopOp(right,ic,FALSE);
10649   pic16_aopOp(left,ic,FALSE);
10650   pic16_aopOp(result,ic,TRUE);
10651
10652   sign = !SPEC_USIGN(operandType (left));
10653   signedCount = !SPEC_USIGN(operandType (right));
10654
10655   /* if the shift count is known then do it 
10656      as efficiently as possible */
10657   if (AOP_TYPE(right) == AOP_LIT) {
10658     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10659     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10660     // we should modify right->aopu.aop_lit here!
10661     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10662     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10663     if (isShiftLeft)
10664       pic16_genLeftShiftLiteral (left,right,result,ic);
10665     else
10666       genRightShiftLiteral (left,right,result,ic, sign);
10667
10668     goto release;
10669   } // if (right is literal)
10670
10671   /* shift count is unknown then we have to form a loop.
10672    * Note: we take only the lower order byte since shifting
10673    * more than 32 bits make no sense anyway, ( the
10674    * largest size of an object can be only 32 bits )
10675    * Note: we perform arithmetic shifts if the left operand is
10676    * signed and we do an (effective) right shift, i. e. we
10677    * shift in the sign bit from the left. */
10678    
10679   label_complete = newiTempLabel ( NULL );
10680   label_loop_pos = newiTempLabel ( NULL );
10681   label_loop_neg = NULL;
10682   label_negative = NULL;
10683   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10684   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10685
10686   if (signedCount) {
10687     // additional labels needed
10688     label_loop_neg = newiTempLabel ( NULL );
10689     label_negative = newiTempLabel ( NULL );
10690   } // if
10691
10692   // copy source to result -- this will effectively truncate the left operand to the size of result!
10693   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10694   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10695   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10696     pic16_mov2f (AOP(result),AOP(left), offset);
10697   } // for
10698
10699   // if result is longer than left, fill with zeros (or sign)
10700   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10701     if (sign && AOP_SIZE(left) > 0) {
10702       // shift signed operand -- fill with sign
10703       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10704       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10705       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10706       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10707         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10708       } // for
10709     } else {
10710       // shift unsigned operand -- fill result with zeros
10711       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10712         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10713       } // for
10714     }
10715   } // if (size mismatch)
10716
10717   pic16_mov2w (AOP(right), 0);
10718   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10719   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10720   
10721 #if 0
10722   // perform a shift by one (shift count is positive)
10723   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10724   // 2n+[2,3]+({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])
10725   pic16_emitpLabel (label_loop_pos->key);
10726   emitCLRC;
10727   if (sign && (pos_shift == POC_RRCF)) {
10728     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10729     emitSETC;
10730   } // if
10731   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10732   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10733   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10734 #else
10735   // perform a shift by one (shift count is positive)
10736   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10737   // 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])
10738   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10739   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10740   emitCLRC;
10741   pic16_emitpLabel (label_loop_pos->key);
10742   if (sign && (pos_shift == POC_RRCF)) {
10743     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10744     emitSETC;
10745   } // if
10746   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10747   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10748   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10749   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10750 #endif
10751
10752   if (signedCount) {
10753     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10754
10755     pic16_emitpLabel (label_negative->key);
10756     // perform a shift by -1 (shift count is negative)
10757     // 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)
10758     emitCLRC;
10759     pic16_emitpLabel (label_loop_neg->key);
10760     if (sign && (neg_shift == POC_RRCF)) {
10761       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10762       emitSETC;
10763     } // if
10764     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10765     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10766     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10767     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10768   } // if (signedCount)
10769
10770   pic16_emitpLabel (label_complete->key);
10771
10772 release:
10773   pic16_freeAsmop (right,NULL,ic,TRUE);
10774   pic16_freeAsmop(left,NULL,ic,TRUE);
10775   pic16_freeAsmop(result,NULL,ic,TRUE);
10776 }
10777
10778 static void genLeftShift (iCode *ic) {
10779   genGenericShift (ic, 1);
10780 }
10781
10782 static void genRightShift (iCode *ic) {
10783   genGenericShift (ic, 0);
10784 }
10785 #endif
10786
10787
10788 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10789 void pic16_loadFSR0(operand *op, int lit)
10790 {
10791   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10792     if (AOP_TYPE(op) == AOP_LIT) {
10793       /* handle 12 bit integers correctly */
10794       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10795       if ((val & 0x0fff) != val) {
10796         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10797                 val, (val & 0x0fff) );
10798         val &= 0x0fff;
10799       }
10800       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10801     } else {
10802       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10803     }
10804   } else {
10805     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10806     // set up FSR0 with address of result
10807     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10808     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10809   }
10810 }
10811
10812 /*----------------------------------------------------------------*/
10813 /* pic16_derefPtr - move one byte from the location ptr points to */
10814 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10815 /*                  to the location ptr points to (doWrite != 0)   */
10816 /*----------------------------------------------------------------*/
10817 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10818 {
10819   if (!IS_PTR(operandType(ptr)))
10820   {
10821     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10822     else pic16_mov2w (AOP(ptr), 0);
10823     return;
10824   }
10825
10826   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10827   /* We might determine pointer type right here: */
10828   p_type = DCL_TYPE(operandType(ptr));
10829
10830   switch (p_type) {
10831     case FPOINTER:
10832     case POINTER:
10833       if (!fsr0_setup || !*fsr0_setup)
10834       {
10835         pic16_loadFSR0( ptr, 0 );
10836         if (fsr0_setup) *fsr0_setup = 1;
10837       }
10838       if (doWrite)
10839         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10840       else
10841         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10842       break;
10843
10844     case GPOINTER:
10845       if (AOP(ptr)->aopu.aop_reg[2]) {
10846         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10847         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10848         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10849         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10850         pic16_mov2w(AOP(ptr), 2);
10851         pic16_callGenericPointerRW(doWrite, 1);
10852       } else {
10853         // data pointer (just 2 byte given)
10854         if (!fsr0_setup || !*fsr0_setup)
10855         {
10856           pic16_loadFSR0( ptr, 0 );
10857           if (fsr0_setup) *fsr0_setup = 1;
10858         }
10859         if (doWrite)
10860           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10861         else
10862           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10863       }
10864       break;
10865
10866     default:
10867       assert (0 && "invalid pointer type specified");
10868       break;
10869   }
10870 }
10871
10872 /*-----------------------------------------------------------------*/
10873 /* genUnpackBits - generates code for unpacking bits               */
10874 /*-----------------------------------------------------------------*/
10875 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10876 {    
10877   int shCnt ;
10878   sym_link *etype, *letype;
10879   int blen=0, bstr=0;
10880   int lbstr;
10881   int same;
10882   pCodeOp *op;
10883
10884   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10885   etype = getSpec(operandType(result));
10886   letype = getSpec(operandType(left));
10887
10888   //    if(IS_BITFIELD(etype)) {
10889   blen = SPEC_BLEN(etype);
10890   bstr = SPEC_BSTR(etype);
10891   //    }
10892
10893   lbstr = SPEC_BSTR( letype );
10894
10895   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10896       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10897
10898 #if 1
10899   if((blen == 1) && (bstr < 8)
10900       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10901     /* it is a single bit, so use the appropriate bit instructions */
10902     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10903
10904     same = pic16_sameRegs(AOP(left),AOP(result));
10905     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10906     pic16_emitpcode(POC_CLRF, op);
10907
10908     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10909       /* workaround to reduce the extra lfsr instruction */
10910       pic16_emitpcode(POC_BTFSC,
10911           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10912     } else {
10913       assert (PIC_IS_DATA_PTR (operandType(left)));
10914       pic16_loadFSR0 (left, 0);
10915       pic16_emitpcode(POC_BTFSC,
10916           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10917     }
10918
10919     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10920       /* unsigned bitfields result in either 0 or 1 */
10921       pic16_emitpcode(POC_INCF, op);
10922     } else {
10923       /* signed bitfields result in either 0 or -1 */
10924       pic16_emitpcode(POC_DECF, op);
10925     }
10926     if (same) {
10927       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10928     }
10929
10930     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10931     return;
10932   }
10933
10934 #endif
10935
10936   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10937     // access symbol directly
10938     pic16_mov2w (AOP(left), 0);
10939   } else {
10940     pic16_derefPtr (left, ptype, 0, NULL);
10941   }
10942
10943   /* if we have bitdisplacement then it fits   */
10944   /* into this byte completely or if length is */
10945   /* less than a byte                          */
10946   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10947
10948     /* shift right acc */
10949     AccRsh(shCnt, 0);
10950
10951     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10952           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10953
10954     /* VR -- normally I would use the following, but since we use the hack,
10955      * to avoid the masking from AccRsh, why not mask it right now? */
10956
10957     /*
10958        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10959      */
10960
10961     /* extend signed bitfields to 8 bits */
10962     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10963     {
10964       assert (blen + bstr > 0);
10965       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10966       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10967     }
10968
10969     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10970
10971     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10972     return ;
10973   }
10974
10975   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10976   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10977   exit(EXIT_FAILURE);
10978
10979   return ;
10980 }
10981
10982
10983 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10984 {
10985   int size, offset = 0, leoffset=0 ;
10986
10987         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10988         pic16_aopOp(result, ic, TRUE);
10989
10990         FENTRY;
10991
10992         size = AOP_SIZE(result);
10993 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10994
10995
10996 #if 1
10997         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10998                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10999                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
11000                 goto release;
11001         }
11002 #endif
11003
11004         if(AOP(left)->aopu.pcop->type == PO_DIR)
11005                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
11006
11007         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11008
11009         while (size--) {
11010                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
11011                 
11012 //              pic16_DumpOp("(result)",result);
11013                 if(is_LitAOp(AOP(result))) {
11014                         pic16_mov2w(AOP(left), offset); // patch 8
11015                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
11016                 } else {
11017                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
11018                                 pic16_popGet(AOP(left), offset), //patch 8
11019                                 pic16_popGet(AOP(result), offset)));
11020                 }
11021
11022                 offset++;
11023                 leoffset++;
11024         }
11025
11026 release:
11027     pic16_freeAsmop(result,NULL,ic,TRUE);
11028 }
11029
11030
11031
11032 /*-----------------------------------------------------------------*/
11033 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
11034 /*-----------------------------------------------------------------*/
11035 static void genNearPointerGet (operand *left, 
11036                                operand *result, 
11037                                iCode *ic)
11038 {
11039 //  asmop *aop = NULL;
11040   //regs *preg = NULL ;
11041   sym_link *rtype, *retype;
11042   sym_link *ltype, *letype;
11043
11044     FENTRY;
11045     
11046     rtype = operandType(result);
11047     retype= getSpec(rtype);
11048     ltype = operandType(left);
11049     letype= getSpec(ltype);
11050     
11051     pic16_aopOp(left,ic,FALSE);
11052
11053 //    pic16_DumpOp("(left)",left);
11054 //    pic16_DumpOp("(result)",result);
11055
11056     /* if left is rematerialisable and
11057      * result is not bit variable type and
11058      * the left is pointer to data space i.e
11059      * lower 128 bytes of space */
11060     
11061     if (AOP_TYPE(left) == AOP_PCODE
11062       && !IS_BITFIELD(retype)
11063       && DCL_TYPE(ltype) == POINTER) {
11064
11065         genDataPointerGet (left,result,ic);
11066         pic16_freeAsmop(left, NULL, ic, TRUE);
11067         return ;
11068     }
11069     
11070     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11071     pic16_aopOp (result,ic,TRUE);
11072     
11073     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
11074
11075 #if 1
11076     if(IS_BITFIELD( retype )
11077       && (SPEC_BLEN(operandType(result))==1)
11078     ) {
11079       iCode *nextic;
11080       pCodeOp *jop;
11081       int bitstrt, bytestrt;
11082
11083         /* if this is bitfield of size 1, see if we are checking the value
11084          * of a single bit in an if-statement,
11085          * if yes, then don't generate usual code, but execute the
11086          * genIfx directly -- VR */
11087
11088         nextic = ic->next;
11089
11090         /* CHECK: if next iCode is IFX
11091          * and current result operand is nextic's conditional operand
11092          * and current result operand live ranges ends at nextic's key number
11093          */
11094         if((nextic->op == IFX)
11095           && (result == IC_COND(nextic))
11096           && (OP_LIVETO(result) == nextic->seq)
11097           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
11098           ) {
11099             /* everything is ok then */
11100             /* find a way to optimize the genIfx iCode */
11101
11102             bytestrt = SPEC_BSTR(operandType(result))/8;
11103             bitstrt = SPEC_BSTR(operandType(result))%8;
11104             
11105             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
11106
11107             genIfxpCOpJump(nextic, jop);
11108             
11109             pic16_freeAsmop(left, NULL, ic, TRUE);
11110             pic16_freeAsmop(result, NULL, ic, TRUE);
11111             return;
11112         }
11113     }
11114 #endif
11115
11116     /* if bitfield then unpack the bits */
11117     if (IS_BITFIELD(letype)) 
11118       genUnpackBits (result, left, NULL, POINTER);
11119     else {
11120       /* we have can just get the values */
11121       int size = AOP_SIZE(result);
11122       int offset = 0;   
11123         
11124       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11125
11126       pic16_loadFSR0( left, 0 );
11127
11128       while(size--) {
11129         if(size) {
11130           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
11131                 pic16_popGet(AOP(result), offset++)));
11132         } else {
11133           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
11134                 pic16_popGet(AOP(result), offset++)));
11135         }
11136       }
11137     }
11138
11139 #if 0
11140     /* now some housekeeping stuff */
11141     if (aop) {
11142       /* we had to allocate for this iCode */
11143       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11144       pic16_freeAsmop(NULL,aop,ic,TRUE);
11145     } else { 
11146       /* we did not allocate which means left
11147        * already in a pointer register, then
11148        * if size > 0 && this could be used again
11149        * we have to point it back to where it 
11150        * belongs */
11151       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11152       if (AOP_SIZE(result) > 1
11153         && !OP_SYMBOL(left)->remat
11154         && ( OP_SYMBOL(left)->liveTo > ic->seq
11155             || ic->depth )) {
11156 //        int size = AOP_SIZE(result) - 1;
11157 //        while (size--)
11158 //          pic16_emitcode("dec","%s",rname);
11159         }
11160     }
11161 #endif
11162
11163     /* done */
11164     pic16_freeAsmop(left,NULL,ic,TRUE);
11165     pic16_freeAsmop(result,NULL,ic,TRUE);
11166 }
11167
11168 /*-----------------------------------------------------------------*/
11169 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
11170 /*-----------------------------------------------------------------*/
11171 static void genPagedPointerGet (operand *left, 
11172                                operand *result, 
11173                                iCode *ic)
11174 {
11175     asmop *aop = NULL;
11176     regs *preg = NULL ;
11177     char *rname ;
11178     sym_link *rtype, *retype;    
11179
11180     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11181
11182     rtype = operandType(result);
11183     retype= getSpec(rtype);
11184     
11185     pic16_aopOp(left,ic,FALSE);
11186
11187   /* if the value is already in a pointer register
11188        then don't need anything more */
11189     if (!AOP_INPREG(AOP(left))) {
11190         /* otherwise get a free pointer register */
11191         aop = newAsmop(0);
11192         preg = getFreePtr(ic,&aop,FALSE);
11193         pic16_emitcode("mov","%s,%s",
11194                 preg->name,
11195                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
11196         rname = preg->name ;
11197     } else
11198         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
11199     
11200     pic16_freeAsmop(left,NULL,ic,TRUE);
11201     pic16_aopOp (result,ic,TRUE);
11202
11203     /* if bitfield then unpack the bits */
11204     if (IS_BITFIELD(retype)) 
11205         genUnpackBits (result,left,rname,PPOINTER);
11206     else {
11207         /* we have can just get the values */
11208         int size = AOP_SIZE(result);
11209         int offset = 0 ;        
11210         
11211         while (size--) {
11212             
11213             pic16_emitcode("movx","a,@%s",rname);
11214             pic16_aopPut(AOP(result),"a",offset);
11215             
11216             offset++ ;
11217             
11218             if (size)
11219                 pic16_emitcode("inc","%s",rname);
11220         }
11221     }
11222
11223     /* now some housekeeping stuff */
11224     if (aop) {
11225         /* we had to allocate for this iCode */
11226         pic16_freeAsmop(NULL,aop,ic,TRUE);
11227     } else { 
11228         /* we did not allocate which means left
11229            already in a pointer register, then
11230            if size > 0 && this could be used again
11231            we have to point it back to where it 
11232            belongs */
11233         if (AOP_SIZE(result) > 1 &&
11234             !OP_SYMBOL(left)->remat &&
11235             ( OP_SYMBOL(left)->liveTo > ic->seq ||
11236               ic->depth )) {
11237             int size = AOP_SIZE(result) - 1;
11238             while (size--)
11239                 pic16_emitcode("dec","%s",rname);
11240         }
11241     }
11242
11243     /* done */
11244     pic16_freeAsmop(result,NULL,ic,TRUE);
11245     
11246         
11247 }
11248
11249 #if 0
11250 /* This code is not adjusted to PIC16 and fails utterly.
11251  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
11252
11253 /*-----------------------------------------------------------------*/
11254 /* genFarPointerGet - gget value from far space                    */
11255 /*-----------------------------------------------------------------*/
11256 static void genFarPointerGet (operand *left,
11257                               operand *result, iCode *ic)
11258 {
11259     int size, offset ;
11260     sym_link *retype = getSpec(operandType(result));
11261
11262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11263
11264     pic16_aopOp(left,ic,FALSE);
11265
11266     /* if the operand is already in dptr 
11267     then we do nothing else we move the value to dptr */
11268     if (AOP_TYPE(left) != AOP_STR) {
11269         /* if this is remateriazable */
11270         if (AOP_TYPE(left) == AOP_IMMD)
11271             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11272         else { /* we need to get it byte by byte */
11273             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11274             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11275             if (options.model == MODEL_FLAT24)
11276             {
11277                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11278             }
11279         }
11280     }
11281     /* so dptr know contains the address */
11282     pic16_freeAsmop(left,NULL,ic,TRUE);
11283     pic16_aopOp(result,ic,TRUE);
11284
11285     /* if bit then unpack */
11286     if (IS_BITFIELD(retype)) 
11287         genUnpackBits(result,left,"dptr",FPOINTER);
11288     else {
11289         size = AOP_SIZE(result);
11290         offset = 0 ;
11291
11292         while (size--) {
11293             pic16_emitcode("movx","a,@dptr");
11294             pic16_aopPut(AOP(result),"a",offset++);
11295             if (size)
11296                 pic16_emitcode("inc","dptr");
11297         }
11298     }
11299
11300     pic16_freeAsmop(result,NULL,ic,TRUE);
11301 }
11302 #endif
11303
11304 #if 0
11305 /*-----------------------------------------------------------------*/
11306 /* genCodePointerGet - get value from code space                  */
11307 /*-----------------------------------------------------------------*/
11308 static void genCodePointerGet (operand *left,
11309                                 operand *result, iCode *ic)
11310 {
11311     int size, offset ;
11312     sym_link *retype = getSpec(operandType(result));
11313
11314     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11315
11316     pic16_aopOp(left,ic,FALSE);
11317
11318     /* if the operand is already in dptr 
11319     then we do nothing else we move the value to dptr */
11320     if (AOP_TYPE(left) != AOP_STR) {
11321         /* if this is remateriazable */
11322         if (AOP_TYPE(left) == AOP_IMMD)
11323             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11324         else { /* we need to get it byte by byte */
11325             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11326             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11327             if (options.model == MODEL_FLAT24)
11328             {
11329                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11330             }
11331         }
11332     }
11333     /* so dptr know contains the address */
11334     pic16_freeAsmop(left,NULL,ic,TRUE);
11335     pic16_aopOp(result,ic,FALSE);
11336
11337     /* if bit then unpack */
11338     if (IS_BITFIELD(retype)) 
11339         genUnpackBits(result,left,"dptr",CPOINTER);
11340     else {
11341         size = AOP_SIZE(result);
11342         offset = 0 ;
11343
11344         while (size--) {
11345             pic16_emitcode("clr","a");
11346             pic16_emitcode("movc","a,@a+dptr");
11347             pic16_aopPut(AOP(result),"a",offset++);
11348             if (size)
11349                 pic16_emitcode("inc","dptr");
11350         }
11351     }
11352
11353     pic16_freeAsmop(result,NULL,ic,TRUE);
11354 }
11355 #endif
11356
11357 #if 0
11358 /*-----------------------------------------------------------------*/
11359 /* genGenPointerGet - gget value from generic pointer space        */
11360 /*-----------------------------------------------------------------*/
11361 static void genGenPointerGet (operand *left,
11362                               operand *result, iCode *ic)
11363 {
11364   int size, offset, lit;
11365   sym_link *retype = getSpec(operandType(result));
11366
11367         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11368         pic16_aopOp(left,ic,FALSE);
11369         pic16_aopOp(result,ic,FALSE);
11370         size = AOP_SIZE(result);
11371
11372         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11373
11374         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11375
11376                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11377                 // load FSR0 from immediate
11378                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11379
11380 //              pic16_loadFSR0( left );
11381
11382                 offset = 0;
11383                 while(size--) {
11384                         if(size) {
11385                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11386                         } else {
11387                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11388                         }
11389                         offset++;
11390                 }
11391                 goto release;
11392
11393         }
11394         else { /* we need to get it byte by byte */
11395                 // set up FSR0 with address from left
11396                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11397                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11398                 
11399                 offset = 0 ;
11400
11401                 while(size--) {
11402                         if(size) {
11403                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11404                         } else {
11405                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11406                         }
11407                         offset++;
11408                 }
11409                 goto release;
11410         }
11411
11412   /* if bit then unpack */
11413         if (IS_BITFIELD(retype)) 
11414                 genUnpackBits(result,left,"BAD",GPOINTER);
11415
11416         release:
11417         pic16_freeAsmop(left,NULL,ic,TRUE);
11418         pic16_freeAsmop(result,NULL,ic,TRUE);
11419
11420 }
11421 #endif
11422
11423
11424 /*-----------------------------------------------------------------*/
11425 /* genGenPointerGet - gget value from generic pointer space        */
11426 /*-----------------------------------------------------------------*/
11427 static void genGenPointerGet (operand *left,
11428                               operand *result, iCode *ic)
11429 {
11430   int size, offset, lit;
11431   sym_link *letype = getSpec(operandType(left));
11432
11433     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11434     pic16_aopOp(left,ic,FALSE);
11435     pic16_aopOp(result,ic,TRUE);
11436     size = AOP_SIZE(result);
11437
11438     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11439   
11440     /* if bit then unpack */
11441     if (IS_BITFIELD(letype)) {
11442       genUnpackBits(result,left,"BAD",GPOINTER);
11443       goto release;
11444     }
11445
11446     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11447
11448       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11449       // load FSR0 from immediate
11450       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11451
11452       werror(W_POSSBUG2, __FILE__, __LINE__);
11453
11454       offset = 0;
11455       while(size--) {
11456         if(size) {
11457           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11458         } else {
11459           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11460         }
11461         offset++;
11462       }
11463
11464       goto release;
11465
11466     } else { /* we need to get it byte by byte */
11467
11468       /* set up WREG:PRODL:FSR0L with address from left */
11469       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11470       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11471       pic16_mov2w(AOP(left), 2);
11472       pic16_callGenericPointerRW(0, size);
11473       
11474       assignResultValue(result, size, 1);
11475       
11476       goto release;
11477     }
11478
11479 release:
11480   pic16_freeAsmop(left,NULL,ic,TRUE);
11481   pic16_freeAsmop(result,NULL,ic,TRUE);
11482 }
11483
11484 /*-----------------------------------------------------------------*/
11485 /* genConstPointerGet - get value from const generic pointer space */
11486 /*-----------------------------------------------------------------*/
11487 static void genConstPointerGet (operand *left,
11488                                 operand *result, iCode *ic)
11489 {
11490   //sym_link *retype = getSpec(operandType(result));
11491   // symbol *albl = newiTempLabel(NULL);        // patch 15
11492   // symbol *blbl = newiTempLabel(NULL);        //
11493   // PIC_OPCODE poc;                            // patch 15
11494   int size;
11495   int offset = 0;
11496
11497   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11498   pic16_aopOp(left,ic,FALSE);
11499   pic16_aopOp(result,ic,TRUE);
11500   size = AOP_SIZE(result);
11501
11502   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11503
11504   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11505
11506   // set up table pointer
11507   if( (AOP_TYPE(left) == AOP_PCODE) 
11508       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11509           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11510     {
11511       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11512       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11513       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11514       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11515       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11516       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11517   } else {
11518     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11519     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11520     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11521   }
11522
11523   while(size--) {
11524     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11525     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11526     offset++;
11527   }
11528     
11529   pic16_freeAsmop(left,NULL,ic,TRUE);
11530   pic16_freeAsmop(result,NULL,ic,TRUE);
11531 }
11532
11533
11534 /*-----------------------------------------------------------------*/
11535 /* genPointerGet - generate code for pointer get                   */
11536 /*-----------------------------------------------------------------*/
11537 static void genPointerGet (iCode *ic)
11538 {
11539   operand *left, *result ;
11540   sym_link *type, *etype;
11541   int p_type;
11542
11543     FENTRY;
11544     
11545     left = IC_LEFT(ic);
11546     result = IC_RESULT(ic) ;
11547
11548     /* depending on the type of pointer we need to
11549     move it to the correct pointer register */
11550     type = operandType(left);
11551     etype = getSpec(type);
11552
11553 #if 0
11554     if (IS_PTR_CONST(type))
11555 #else
11556     if (IS_CODEPTR(type))
11557 #endif
11558       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11559
11560     /* if left is of type of pointer then it is simple */
11561     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11562       p_type = DCL_TYPE(type);
11563     else {
11564       /* we have to go by the storage class */
11565       p_type = PTR_TYPE(SPEC_OCLS(etype));
11566
11567       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11568
11569       if (SPEC_OCLS(etype)->codesp ) {
11570         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11571         //p_type = CPOINTER ;   
11572       } else
11573       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11574         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11575         /*p_type = FPOINTER ;*/ 
11576       } else
11577       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11578         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11579         /* p_type = PPOINTER; */
11580       } else
11581       if (SPEC_OCLS(etype) == idata ) {
11582         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11583         /* p_type = IPOINTER; */
11584       } else {
11585         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11586         /* p_type = POINTER ; */
11587       }
11588     }
11589
11590     /* now that we have the pointer type we assign
11591     the pointer values */
11592     switch (p_type) {
11593       case POINTER:     
11594       case FPOINTER:
11595       case IPOINTER:
11596         genNearPointerGet (left,result,ic);
11597         break;
11598
11599       case PPOINTER:
11600         genPagedPointerGet(left,result,ic);
11601         break;
11602
11603 #if 0
11604       /* PICs do not support FAR pointers... */
11605       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11606       case FPOINTER:
11607         genFarPointerGet (left,result,ic);
11608         break;
11609 #endif
11610
11611       case CPOINTER:
11612         genConstPointerGet (left,result,ic);
11613         //pic16_emitcodePointerGet (left,result,ic);
11614         break;
11615
11616       case GPOINTER:
11617 #if 0
11618       if (IS_PTR_CONST(type))
11619         genConstPointerGet (left,result,ic);
11620       else
11621 #endif
11622         genGenPointerGet (left,result,ic);
11623       break;
11624
11625     default:
11626       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11627               "genPointerGet: illegal pointer type");
11628     
11629     }
11630 }
11631
11632 /*-----------------------------------------------------------------*/
11633 /* genPackBits - generates code for packed bit storage             */
11634 /*-----------------------------------------------------------------*/
11635 static void genPackBits (sym_link    *etype , operand *result,
11636                          operand *right ,
11637                          char *rname, int p_type)
11638 {
11639   int shCnt = 0 ;
11640   int offset = 0  ;
11641   int rLen = 0 ;
11642   int blen, bstr ;   
11643   int shifted_and_masked = 0;
11644   unsigned long lit = (unsigned long)-1;
11645   sym_link *retype;
11646
11647   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11648   blen = SPEC_BLEN(etype);
11649   bstr = SPEC_BSTR(etype);
11650
11651   retype = getSpec(operandType(right));
11652
11653   if(AOP_TYPE(right) == AOP_LIT) {
11654     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11655     
11656     if((blen == 1) && (bstr < 8)) {
11657       /* it is a single bit, so use the appropriate bit instructions */
11658
11659       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11660
11661       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11662         /* workaround to reduce the extra lfsr instruction */
11663         if(lit) {
11664           pic16_emitpcode(POC_BSF,
11665               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11666         } else {
11667           pic16_emitpcode(POC_BCF,
11668               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11669         }
11670       } else {
11671         if (PIC_IS_DATA_PTR(operandType(result))) {
11672           pic16_loadFSR0(result, 0);
11673           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11674               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11675         } else {
11676           /* get old value */
11677           pic16_derefPtr (result, p_type, 0, NULL);
11678           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11679               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11680           /* write back new value */
11681           pic16_derefPtr (result, p_type, 1, NULL);
11682         }
11683       }
11684
11685       return;
11686     }
11687     /* IORLW below is more efficient */
11688     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11689     lit = (lit & ((1UL << blen) - 1)) << bstr;
11690     shifted_and_masked = 1;
11691     offset++;
11692   } else
11693     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11694         && IS_BITFIELD(retype) 
11695         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11696         && (blen == 1)) {
11697       int rblen, rbstr;
11698
11699       rblen = SPEC_BLEN( retype );
11700       rbstr = SPEC_BSTR( retype );
11701
11702       if(IS_BITFIELD(etype)) {
11703         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11704         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11705       } else {
11706         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11707       }
11708
11709       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11710
11711       if(IS_BITFIELD(etype)) {
11712         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11713       } else {
11714         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11715       }
11716
11717       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11718
11719       return;
11720     } else {
11721       /* move right to W */
11722       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11723     }
11724
11725   /* if the bit length is less than or   */
11726   /* it exactly fits a byte then         */
11727   if((shCnt=SPEC_BSTR(etype))
11728       || SPEC_BLEN(etype) <= 8 )  {
11729     int fsr0_setup = 0;
11730
11731     if (blen != 8 || (bstr % 8) != 0) {
11732       // we need to combine the value with the old value
11733       if(!shifted_and_masked)
11734       {
11735         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11736
11737         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11738             SPEC_BSTR(etype), SPEC_BLEN(etype));
11739
11740         /* shift left acc, do NOT mask the result again */
11741         AccLsh(shCnt, 0);
11742
11743         /* using PRODH as a temporary register here */
11744         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11745       }
11746
11747       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11748         || IS_DIRECT(result)) {
11749         /* access symbol directly */
11750         pic16_mov2w (AOP(result), 0);
11751       } else {
11752         /* get old value */
11753         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11754       }
11755 #if 1
11756       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11757             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11758                             (unsigned char)(0xff >> (8-bstr))) ));
11759       if (!shifted_and_masked) {
11760         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11761       } else {
11762         /* We have the shifted and masked (literal) right value in `lit' */
11763         if (lit != 0)
11764           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11765       }
11766     } else { // if (blen == 8 && (bstr % 8) == 0)
11767         if (shifted_and_masked) {
11768             // move right (literal) to WREG (only case where right is not yet in WREG)
11769             pic16_mov2w(AOP(right), (bstr / 8));
11770         }
11771     }
11772
11773     /* write new value back */
11774     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11775         || IS_DIRECT(result)) {
11776       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11777     } else {
11778       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11779     }
11780 #endif
11781
11782     return;
11783   }
11784
11785
11786 #if 0
11787   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11788   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11789   exit(EXIT_FAILURE);
11790 #endif
11791
11792
11793   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11794   rLen = SPEC_BLEN(etype)-8;
11795
11796   /* now generate for lengths greater than one byte */
11797   while (1) {
11798     rLen -= 8 ;
11799     if (rLen <= 0 ) {
11800       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11801       break ;
11802     }
11803
11804     switch (p_type) {
11805       case POINTER:
11806         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11807         break;
11808
11809         /*
11810            case FPOINTER:
11811            MOVA(l);
11812            pic16_emitcode("movx","@dptr,a");
11813            break;
11814
11815            case GPOINTER:
11816            MOVA(l);
11817            DEBUGpic16_emitcode(";lcall","__gptrput");
11818            break;  
11819          */
11820       default:
11821         assert(0);
11822     }   
11823
11824
11825     pic16_mov2w(AOP(right), offset++);
11826   }
11827
11828   /* last last was not complete */
11829   if (rLen)   {
11830     /* save the byte & read byte */
11831     switch (p_type) {
11832       case POINTER:
11833         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11834         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11835         break;
11836
11837         /*
11838            case FPOINTER:
11839            pic16_emitcode ("mov","b,a");
11840            pic16_emitcode("movx","a,@dptr");
11841            break;
11842
11843            case GPOINTER:
11844            pic16_emitcode ("push","b");
11845            pic16_emitcode ("push","acc");
11846            pic16_emitcode ("lcall","__gptrget");
11847            pic16_emitcode ("pop","b");
11848            break;
11849          */
11850       default:
11851         assert(0);
11852     }
11853     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11854     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11855     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11856     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11857     //        pic16_emitcode ("orl","a,b");
11858   }
11859
11860   //    if (p_type == GPOINTER)
11861   //        pic16_emitcode("pop","b");
11862
11863   switch (p_type) {
11864
11865     case POINTER:
11866       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11867       //        pic16_emitcode("mov","@%s,a",rname);
11868       break;
11869       /*
11870          case FPOINTER:
11871          pic16_emitcode("movx","@dptr,a");
11872          break;
11873
11874          case GPOINTER:
11875          DEBUGpic16_emitcode(";lcall","__gptrput");
11876          break;                 
11877        */
11878     default:
11879       assert(0);
11880   }
11881
11882   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11883 }
11884
11885 /*-----------------------------------------------------------------*/
11886 /* genDataPointerSet - remat pointer to data space                 */
11887 /*-----------------------------------------------------------------*/
11888 static void genDataPointerSet(operand *right,
11889                               operand *result,
11890                               iCode *ic)
11891 {
11892   int size, offset = 0, resoffset=0 ;
11893
11894     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11895     pic16_aopOp(right,ic,FALSE);
11896
11897     size = AOP_SIZE(right);
11898
11899 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11900
11901 #if 0
11902     if ( AOP_TYPE(result) == AOP_PCODE) {
11903       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11904               AOP(result)->aopu.pcop->name,
11905                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11906               PCOR(AOP(result)->aopu.pcop)->instance:
11907               PCOI(AOP(result)->aopu.pcop)->offset);
11908     }
11909 #endif
11910
11911     if(AOP(result)->aopu.pcop->type == PO_DIR)
11912       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11913
11914     while (size--) {
11915       if (AOP_TYPE(right) == AOP_LIT) {
11916         unsigned int lit = pic16aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
11917         pic16_movLit2f(pic16_popGet(AOP(result), offset), lit);
11918       } else {
11919         pic16_mov2w(AOP(right), offset);
11920         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); // patch 8
11921       }
11922       offset++;
11923       resoffset++;
11924     }
11925
11926     pic16_freeAsmop(right,NULL,ic,TRUE);
11927 }
11928
11929
11930
11931 /*-----------------------------------------------------------------*/
11932 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11933 /*-----------------------------------------------------------------*/
11934 static void genNearPointerSet (operand *right,
11935                                operand *result, 
11936                                iCode *ic)
11937 {
11938   asmop *aop = NULL;
11939   sym_link *retype;
11940   sym_link *ptype = operandType(result);
11941   sym_link *resetype;
11942     
11943     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11944     retype= getSpec(operandType(right));
11945     resetype = getSpec(operandType(result));
11946   
11947     pic16_aopOp(result,ic,FALSE);
11948     
11949     /* if the result is rematerializable &
11950      * in data space & not a bit variable */
11951         
11952     /* and result is not a bit variable */
11953     if (AOP_TYPE(result) == AOP_PCODE
11954 //      && AOP_TYPE(result) == AOP_IMMD
11955       && DCL_TYPE(ptype) == POINTER
11956       && !IS_BITFIELD(retype)
11957       && !IS_BITFIELD(resetype)) {
11958
11959         genDataPointerSet (right,result,ic);
11960         pic16_freeAsmop(result,NULL,ic,TRUE);
11961       return;
11962     }
11963
11964     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11965     pic16_aopOp(right,ic,FALSE);
11966     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11967
11968     /* if bitfield then unpack the bits */
11969     if (IS_BITFIELD(resetype)) {
11970       genPackBits (resetype, result, right, NULL, POINTER);
11971     } else {
11972       /* we have can just get the values */
11973       int size = AOP_SIZE(right);
11974       int offset = 0 ;    
11975
11976         pic16_loadFSR0(result, 0);
11977             
11978         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11979         while (size--) {
11980           if (is_LitOp(right)) {
11981             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11982             if (size) {
11983               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11984             } else {
11985               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11986             }
11987           } else { // no literal
11988             if(size) {
11989               pic16_emitpcode(POC_MOVFF,
11990                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11991                   pic16_popCopyReg(&pic16_pc_postinc0)));
11992             } else {
11993               pic16_emitpcode(POC_MOVFF,
11994                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11995                   pic16_popCopyReg(&pic16_pc_indf0)));
11996             }
11997           }
11998           
11999           offset++;
12000         }
12001     }
12002
12003     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12004     /* now some housekeeping stuff */
12005     if (aop) {
12006       /* we had to allocate for this iCode */
12007       pic16_freeAsmop(NULL,aop,ic,TRUE);
12008     } else { 
12009       /* we did not allocate which means left
12010        * already in a pointer register, then
12011        * if size > 0 && this could be used again
12012        * we have to point it back to where it 
12013        * belongs */
12014       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12015       if (AOP_SIZE(right) > 1
12016         && !OP_SYMBOL(result)->remat
12017         && ( OP_SYMBOL(result)->liveTo > ic->seq
12018         || ic->depth )) {
12019
12020           int size = AOP_SIZE(right) - 1;
12021
12022             while (size--)
12023               pic16_emitcode("decf","fsr0,f");
12024               //pic16_emitcode("dec","%s",rname);
12025       }
12026     }
12027
12028     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12029     /* done */
12030 //release:
12031     pic16_freeAsmop(right,NULL,ic,TRUE);
12032     pic16_freeAsmop(result,NULL,ic,TRUE);
12033 }
12034
12035 /*-----------------------------------------------------------------*/
12036 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
12037 /*-----------------------------------------------------------------*/
12038 static void genPagedPointerSet (operand *right,
12039                                operand *result, 
12040                                iCode *ic)
12041 {
12042     asmop *aop = NULL;
12043     regs *preg = NULL ;
12044     char *rname , *l;
12045     sym_link *retype;
12046        
12047     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12048
12049     retype= getSpec(operandType(right));
12050     
12051     pic16_aopOp(result,ic,FALSE);
12052     
12053     /* if the value is already in a pointer register
12054        then don't need anything more */
12055     if (!AOP_INPREG(AOP(result))) {
12056         /* otherwise get a free pointer register */
12057         aop = newAsmop(0);
12058         preg = getFreePtr(ic,&aop,FALSE);
12059         pic16_emitcode("mov","%s,%s",
12060                 preg->name,
12061                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
12062         rname = preg->name ;
12063     } else
12064         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12065     
12066     pic16_freeAsmop(result,NULL,ic,TRUE);
12067     pic16_aopOp (right,ic,FALSE);
12068
12069     /* if bitfield then unpack the bits */
12070     if (IS_BITFIELD(retype)) 
12071         genPackBits (retype,result,right,rname,PPOINTER);
12072     else {
12073         /* we have can just get the values */
12074         int size = AOP_SIZE(right);
12075         int offset = 0 ;        
12076         
12077         while (size--) {
12078             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
12079             
12080             MOVA(l);
12081             pic16_emitcode("movx","@%s,a",rname);
12082
12083             if (size)
12084                 pic16_emitcode("inc","%s",rname);
12085
12086             offset++;
12087         }
12088     }
12089     
12090     /* now some housekeeping stuff */
12091     if (aop) {
12092         /* we had to allocate for this iCode */
12093         pic16_freeAsmop(NULL,aop,ic,TRUE);
12094     } else { 
12095         /* we did not allocate which means left
12096            already in a pointer register, then
12097            if size > 0 && this could be used again
12098            we have to point it back to where it 
12099            belongs */
12100         if (AOP_SIZE(right) > 1 &&
12101             !OP_SYMBOL(result)->remat &&
12102             ( OP_SYMBOL(result)->liveTo > ic->seq ||
12103               ic->depth )) {
12104             int size = AOP_SIZE(right) - 1;
12105             while (size--)
12106                 pic16_emitcode("dec","%s",rname);
12107         }
12108     }
12109
12110     /* done */
12111     pic16_freeAsmop(right,NULL,ic,TRUE);
12112     
12113         
12114 }
12115
12116 #if 0
12117 /* This code is not adjusted to PIC16 and fails utterly...
12118  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
12119
12120 /*-----------------------------------------------------------------*/
12121 /* genFarPointerSet - set value from far space                     */
12122 /*-----------------------------------------------------------------*/
12123 static void genFarPointerSet (operand *right,
12124                               operand *result, iCode *ic)
12125 {
12126     int size, offset ;
12127     sym_link *retype = getSpec(operandType(right));
12128
12129     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12130     pic16_aopOp(result,ic,FALSE);
12131
12132     /* if the operand is already in dptr 
12133     then we do nothing else we move the value to dptr */
12134     if (AOP_TYPE(result) != AOP_STR) {
12135         /* if this is remateriazable */
12136         if (AOP_TYPE(result) == AOP_IMMD)
12137             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
12138         else { /* we need to get it byte by byte */
12139             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
12140             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
12141             if (options.model == MODEL_FLAT24)
12142             {
12143                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
12144             }
12145         }
12146     }
12147     /* so dptr know contains the address */
12148     pic16_freeAsmop(result,NULL,ic,TRUE);
12149     pic16_aopOp(right,ic,FALSE);
12150
12151     /* if bit then unpack */
12152     if (IS_BITFIELD(retype)) 
12153         genPackBits(retype,result,right,"dptr",FPOINTER);
12154     else {
12155         size = AOP_SIZE(right);
12156         offset = 0 ;
12157
12158         while (size--) {
12159             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12160             MOVA(l);
12161             pic16_emitcode("movx","@dptr,a");
12162             if (size)
12163                 pic16_emitcode("inc","dptr");
12164         }
12165     }
12166
12167     pic16_freeAsmop(right,NULL,ic,TRUE);
12168 }
12169 #endif
12170
12171 /*-----------------------------------------------------------------*/
12172 /* genGenPointerSet - set value from generic pointer space         */
12173 /*-----------------------------------------------------------------*/
12174 #if 0
12175 static void genGenPointerSet (operand *right,
12176                               operand *result, iCode *ic)
12177 {
12178         int i, size, offset, lit;
12179         sym_link *retype = getSpec(operandType(right));
12180
12181         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12182
12183         pic16_aopOp(result,ic,FALSE);
12184         pic16_aopOp(right,ic,FALSE);
12185         size = AOP_SIZE(right);
12186         offset = 0;
12187
12188         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12189
12190         /* if the operand is already in dptr 
12191                 then we do nothing else we move the value to dptr */
12192         if (AOP_TYPE(result) != AOP_STR) {
12193                 /* if this is remateriazable */
12194                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12195                 // WARNING: anythig until "else" is untested!
12196                 if (AOP_TYPE(result) == AOP_IMMD) {
12197                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12198                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
12199                         // load FSR0 from immediate
12200                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12201                         offset = 0;
12202                         while(size--) {
12203                                 if(size) {
12204                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12205                                 } else {
12206                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12207                                 }
12208                                 offset++;
12209                         }
12210                         goto release;
12211                 }
12212                 else { /* we need to get it byte by byte */
12213                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12214                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
12215
12216                         // set up FSR0 with address of result
12217                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12218                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12219
12220                         /* hack hack! see if this the FSR. If so don't load W */
12221                         if(AOP_TYPE(right) != AOP_ACC) {
12222
12223                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12224
12225                                 if(AOP_TYPE(right) == AOP_LIT)
12226                                 {
12227                                         // copy literal
12228                                         // note: pic16_popGet handles sign extension
12229                                         for(i=0;i<size;i++) {
12230                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
12231                                                 if(i < size-1)
12232                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
12233                                                 else
12234                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
12235                                         }
12236                                 } else {
12237                                         // copy regs
12238
12239                                         for(i=0;i<size;i++) {
12240                                                 if(i < size-1)
12241                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12242                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
12243                                                 else
12244                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
12245                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12246                                         }
12247                                 }
12248                                 goto release;
12249                         } 
12250                         // right = ACC
12251                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12252                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12253                         goto release;
12254         } // if (AOP_TYPE(result) != AOP_IMMD)
12255
12256         } // if (AOP_TYPE(result) != AOP_STR)
12257         /* so dptr know contains the address */
12258
12259
12260         /* if bit then unpack */
12261         if (IS_BITFIELD(retype)) 
12262                 genPackBits(retype,result,right,"dptr",GPOINTER);
12263         else {
12264                 size = AOP_SIZE(right);
12265                 offset = 0 ;
12266
12267                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12268
12269                 // set up FSR0 with address of result
12270                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12271                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12272         
12273                 while (size--) {
12274                         if (AOP_TYPE(right) == AOP_LIT) {
12275                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12276                                 if (size) {
12277                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12278                                 } else {
12279                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12280                                 }
12281                         } else { // no literal
12282                                 if(size) {
12283                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12284                                 } else {
12285                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12286                                 }
12287                         }
12288                         offset++;
12289                 }
12290         }
12291
12292         release:
12293         pic16_freeAsmop(right,NULL,ic,TRUE);
12294         pic16_freeAsmop(result,NULL,ic,TRUE);
12295 }
12296 #endif
12297
12298 static void genGenPointerSet (operand *right,
12299                               operand *result, iCode *ic)
12300 {
12301   int size;
12302   sym_link *retype = getSpec(operandType(result));
12303
12304     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12305
12306     pic16_aopOp(result,ic,FALSE);
12307     pic16_aopOp(right,ic,FALSE);
12308     size = AOP_SIZE(right);
12309
12310     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12311
12312
12313     /* if bit then unpack */
12314     if (IS_BITFIELD(retype)) {
12315 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12316       genPackBits(retype,result,right,"dptr",GPOINTER);
12317       goto release;
12318     }
12319
12320     size = AOP_SIZE(right);
12321
12322     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12323
12324
12325     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12326
12327     /* value of right+0 is placed on stack, which will be retrieved
12328      * by the support function thus restoring the stack. The important
12329      * thing is that there is no need to manually restore stack pointer
12330      * here */
12331     pushaop(AOP(right), 0);
12332 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12333     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12334     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12335     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12336     
12337     /* load address to write to in WREG:FSR0H:FSR0L */
12338     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12339                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12340     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12341                                 pic16_popCopyReg(&pic16_pc_prodl)));
12342     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12343     
12344     pic16_callGenericPointerRW(1, size);
12345
12346 release:
12347     pic16_freeAsmop(right,NULL,ic,TRUE);
12348     pic16_freeAsmop(result,NULL,ic,TRUE);
12349 }
12350
12351 /*-----------------------------------------------------------------*/
12352 /* genPointerSet - stores the value into a pointer location        */
12353 /*-----------------------------------------------------------------*/
12354 static void genPointerSet (iCode *ic)
12355 {    
12356   operand *right, *result ;
12357   sym_link *type, *etype;
12358   int p_type;
12359
12360     FENTRY;
12361
12362     right = IC_RIGHT(ic);
12363     result = IC_RESULT(ic) ;
12364
12365     /* depending on the type of pointer we need to
12366     move it to the correct pointer register */
12367     type = operandType(result);
12368     etype = getSpec(type);
12369     
12370     /* if left is of type of pointer then it is simple */
12371     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12372         p_type = DCL_TYPE(type);
12373     }
12374     else {
12375         /* we have to go by the storage class */
12376         p_type = PTR_TYPE(SPEC_OCLS(etype));
12377
12378 /*      if (SPEC_OCLS(etype)->codesp ) { */
12379 /*          p_type = CPOINTER ;  */
12380 /*      } */
12381 /*      else */
12382 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12383 /*              p_type = FPOINTER ; */
12384 /*          else */
12385 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12386 /*                  p_type = PPOINTER ; */
12387 /*              else */
12388 /*                  if (SPEC_OCLS(etype) == idata ) */
12389 /*                      p_type = IPOINTER ; */
12390 /*                  else */
12391 /*                      p_type = POINTER ; */
12392     }
12393
12394     /* now that we have the pointer type we assign
12395     the pointer values */
12396     switch (p_type) {
12397       case POINTER:
12398       case FPOINTER:
12399       case IPOINTER:
12400         genNearPointerSet (right,result,ic);
12401         break;
12402
12403       case PPOINTER:
12404         genPagedPointerSet (right,result,ic);
12405         break;
12406
12407 #if 0
12408       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12409       case FPOINTER:
12410         genFarPointerSet (right,result,ic);
12411         break;
12412 #endif
12413         
12414       case GPOINTER:
12415         genGenPointerSet (right,result,ic);
12416         break;
12417
12418       default:
12419         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12420           "genPointerSet: illegal pointer type");
12421     }
12422 }
12423
12424 /*-----------------------------------------------------------------*/
12425 /* genIfx - generate code for Ifx statement                        */
12426 /*-----------------------------------------------------------------*/
12427 static void genIfx (iCode *ic, iCode *popIc)
12428 {
12429   operand *cond = IC_COND(ic);
12430   int isbit =0;
12431
12432     FENTRY;
12433
12434     pic16_aopOp(cond,ic,FALSE);
12435
12436     /* get the value into acc */
12437     if (AOP_TYPE(cond) != AOP_CRY)
12438       pic16_toBoolean(cond);
12439     else
12440       isbit = 1;
12441     /* the result is now in the accumulator */
12442     pic16_freeAsmop(cond,NULL,ic,TRUE);
12443
12444     /* if there was something to be popped then do it */
12445     if (popIc)
12446       genIpop(popIc);
12447
12448     /* if the condition is  a bit variable */
12449     if (isbit && IS_ITEMP(cond) && 
12450         SPIL_LOC(cond)) {
12451       genIfxJump(ic,"c");
12452       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12453     } else {
12454       if (isbit && !IS_ITEMP(cond))
12455         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12456         else
12457         genIfxJump(ic,"a");
12458     }
12459     ic->generated = 1;
12460 }
12461
12462 /*-----------------------------------------------------------------*/
12463 /* genAddrOf - generates code for address of                       */
12464 /*-----------------------------------------------------------------*/
12465 static void genAddrOf (iCode *ic)
12466 {
12467   operand *result, *left;
12468   int size;
12469   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12470   pCodeOp *pcop0, *pcop1, *pcop2;
12471
12472     FENTRY;
12473
12474     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12475
12476     sym = OP_SYMBOL( IC_LEFT(ic) );
12477     
12478     if(sym->onStack) {
12479       /* get address of symbol on stack */
12480       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12481 #if 0
12482       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12483                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12484 #endif
12485
12486       // operands on stack are accessible via "FSR2 + index" with index
12487       // starting at 2 for arguments and growing from 0 downwards for
12488       // local variables (index == 0 is not assigned so we add one here)
12489       {
12490         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12491
12492           if (soffs <= 0) {
12493             assert (soffs < 0);
12494             soffs++;
12495           } // if
12496
12497           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12498           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12499           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12500           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12501           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12502           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12503           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12504       }
12505
12506       goto release;
12507     }
12508         
12509 //      if(pic16_debug_verbose) {
12510 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12511 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12512 //      }
12513         
12514     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12515     size = AOP_SIZE(IC_RESULT(ic));
12516
12517     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12518     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12519     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12520         
12521     if (size == 3) {
12522       pic16_emitpcode(POC_MOVLW, pcop0);
12523       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12524       pic16_emitpcode(POC_MOVLW, pcop1);
12525       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12526       pic16_emitpcode(POC_MOVLW, pcop2);
12527       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12528     } else
12529     if (size == 2) {
12530       pic16_emitpcode(POC_MOVLW, pcop0);
12531       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12532       pic16_emitpcode(POC_MOVLW, pcop1);
12533     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12534     } else {
12535       pic16_emitpcode(POC_MOVLW, pcop0);
12536       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12537     }
12538
12539     pic16_freeAsmop(left, NULL, ic, FALSE);
12540 release:
12541     pic16_freeAsmop(result,NULL,ic,TRUE);
12542 }
12543
12544
12545 #if 0
12546 /*-----------------------------------------------------------------*/
12547 /* genFarFarAssign - assignment when both are in far space         */
12548 /*-----------------------------------------------------------------*/
12549 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12550 {
12551     int size = AOP_SIZE(right);
12552     int offset = 0;
12553     char *l ;
12554     /* first push the right side on to the stack */
12555     while (size--) {
12556         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12557         MOVA(l);
12558         pic16_emitcode ("push","acc");
12559     }
12560     
12561     pic16_freeAsmop(right,NULL,ic,FALSE);
12562     /* now assign DPTR to result */
12563     pic16_aopOp(result,ic,FALSE);
12564     size = AOP_SIZE(result);
12565     while (size--) {
12566         pic16_emitcode ("pop","acc");
12567         pic16_aopPut(AOP(result),"a",--offset);
12568     }
12569     pic16_freeAsmop(result,NULL,ic,FALSE);
12570         
12571 }
12572 #endif
12573
12574 /*-----------------------------------------------------------------*/
12575 /* genAssign - generate code for assignment                        */
12576 /*-----------------------------------------------------------------*/
12577 static void genAssign (iCode *ic)
12578 {
12579   operand *result, *right;
12580   sym_link *restype, *rtype;
12581   int size, offset,know_W;
12582   unsigned long lit = 0L;
12583
12584     result = IC_RESULT(ic);
12585     right  = IC_RIGHT(ic) ;
12586
12587     FENTRY;
12588   
12589     /* if they are the same */
12590     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12591       return ;
12592
12593     /* reversed order operands are aopOp'ed so that result operand
12594      * is effective in case right is a stack symbol. This maneauver
12595      * allows to use the _G.resDirect flag later */
12596      pic16_aopOp(result,ic,TRUE);
12597     pic16_aopOp(right,ic,FALSE);
12598
12599     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12600
12601     /* if they are the same registers */
12602     if (pic16_sameRegs(AOP(right),AOP(result)))
12603       goto release;
12604
12605     /* if the result is a bit */
12606     if (AOP_TYPE(result) == AOP_CRY) {
12607       /* if the right size is a literal then
12608          we know what the value is */
12609       if (AOP_TYPE(right) == AOP_LIT) {
12610           
12611         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12612             pic16_popGet(AOP(result),0));
12613
12614         if (((int) operandLitValue(right))) 
12615           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12616               AOP(result)->aopu.aop_dir,
12617               AOP(result)->aopu.aop_dir);
12618         else
12619           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12620               AOP(result)->aopu.aop_dir,
12621               AOP(result)->aopu.aop_dir);
12622         
12623         goto release;
12624       }
12625
12626       /* the right is also a bit variable */
12627       if (AOP_TYPE(right) == AOP_CRY) {
12628         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12629         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12630         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12631
12632         goto release ;
12633       }
12634
12635       /* we need to or */
12636       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12637       pic16_toBoolean(right);
12638       emitSKPZ;
12639       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12640       //pic16_aopPut(AOP(result),"a",0);
12641       goto release ;
12642     }
12643
12644     /* bit variables done */
12645     /* general case */
12646     size = AOP_SIZE(result);
12647     offset = 0 ;
12648
12649   /* bit variables done */
12650   /* general case */
12651   size = AOP_SIZE(result);
12652   restype = operandType(result);
12653   rtype = operandType(right);
12654   offset = 0 ;
12655
12656   if(AOP_TYPE(right) == AOP_LIT) {
12657     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12658     {
12659       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12660
12661       /* patch tag for literals that are cast to pointers */
12662       if (IS_CODEPTR(restype)) {
12663         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12664         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12665       } else {
12666         if (IS_GENPTR(restype))
12667         {
12668           if (IS_CODEPTR(rtype)) {
12669             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12670             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12671           } else if (PIC_IS_DATA_PTR(rtype)) {
12672             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12673             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12674           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12675             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12676           } else if (IS_PTR(rtype)) {
12677             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12678             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12679           }
12680         }
12681       }
12682     } else {
12683       union {
12684         unsigned long lit_int;
12685         float lit_float;
12686       } info;
12687
12688
12689       if(IS_FIXED16X16(operandType(right))) {
12690         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12691       } else {
12692         /* take care if literal is a float */
12693         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12694         lit = info.lit_int;
12695       }
12696     }
12697   }
12698
12699 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12700 //                      sizeof(unsigned long int), sizeof(float));
12701
12702
12703     if (AOP_TYPE(right) == AOP_REG) {
12704       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12705       while (size--) {
12706         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12707       } // while
12708       goto release;
12709     }
12710
12711     /* when do we have to read the program memory?
12712      * - if right itself is a symbol in code space
12713      *   (we don't care what it points to if it's a pointer)
12714      * - AND right is not a function (we would want its address)
12715      */
12716     if(AOP_TYPE(right) != AOP_LIT
12717       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12718       && !IS_FUNC(OP_SYM_TYPE(right))
12719       && !IS_ITEMP(right)) {
12720
12721       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12722       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12723       
12724       // set up table pointer
12725       if(is_LitOp(right)) {
12726 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12727         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12728         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12729         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12730         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12731         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12732         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12733       } else {
12734 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12735         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12736             pic16_popCopyReg(&pic16_pc_tblptrl)));
12737         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12738             pic16_popCopyReg(&pic16_pc_tblptrh)));
12739         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12740             pic16_popCopyReg(&pic16_pc_tblptru)));
12741       }
12742
12743       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12744       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12745       while(size--) {
12746         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12747         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12748             pic16_popGet(AOP(result),offset)));
12749         offset++;
12750       }
12751
12752       /* FIXME: for pointers we need to extend differently (according
12753        * to pointer type DATA/CODE/EEPROM/... :*/
12754       size = getSize(OP_SYM_TYPE(right));
12755       if(AOP_SIZE(result) > size) {
12756         size = AOP_SIZE(result) - size;
12757         while(size--) {
12758           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12759           offset++;
12760         }
12761       }
12762       goto release;
12763     }
12764
12765 #if 0
12766     /* VR - What is this?! */
12767     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12768       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12769       
12770       if(aopIdx(AOP(result),0) == 4) {
12771         /* this is a workaround to save value of right into wreg too,
12772          * value of wreg is going to be used later */
12773         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12774         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12775         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12776         goto release;
12777       } else
12778 //      assert(0);
12779       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12780     }
12781 #endif
12782
12783     size = AOP_SIZE(right);
12784     if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
12785     know_W=-1;
12786     while (size--) {
12787       DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12788       if(AOP_TYPE(right) == AOP_LIT) {
12789         if(lit&0xff) {
12790           if(know_W != (lit&0xff))
12791             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12792           know_W = lit&0xff;
12793           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12794         } else
12795           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12796
12797         lit >>= 8;
12798
12799       } else if (AOP_TYPE(right) == AOP_CRY) {
12800         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12801         if(offset == 0) {
12802           //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12803           pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12804           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12805         }
12806       } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12807         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12808         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12809       } else {
12810         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12811
12812         if(!_G.resDirect) {                                             /* use this aopForSym feature */
12813           if(AOP_TYPE(result) == AOP_ACC) {
12814             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12815           } else
12816             if(AOP_TYPE(right) == AOP_ACC) {
12817               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12818             } else {
12819               pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12820             }
12821         }
12822       }
12823
12824       offset++;
12825     }
12826     pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
12827   
12828 release:
12829   pic16_freeAsmop (right,NULL,ic,FALSE);
12830   pic16_freeAsmop (result,NULL,ic,TRUE);
12831
12832
12833 /*-----------------------------------------------------------------*/
12834 /* genJumpTab - generates code for jump table                       */
12835 /*-----------------------------------------------------------------*/
12836 static void genJumpTab (iCode *ic)
12837 {
12838   symbol *jtab;
12839   char *l;
12840   pCodeOp *jt_offs;
12841   pCodeOp *jt_offs_hi;
12842   pCodeOp *jt_label;
12843
12844     FENTRY;
12845
12846     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12847     /* get the condition into accumulator */
12848     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12849     MOVA(l);
12850     /* multiply by three */
12851     pic16_emitcode("add","a,acc");
12852     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12853
12854     jtab = newiTempLabel(NULL);
12855     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12856     pic16_emitcode("jmp","@a+dptr");
12857     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12858
12859 #if 0
12860     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12861     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12862     emitSKPNC;
12863     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12864     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12865     pic16_emitpLabel(jtab->key);
12866
12867 #else
12868
12869     jt_offs = pic16_popGetTempReg(0);
12870     jt_offs_hi = pic16_popGetTempReg(1);
12871     jt_label = pic16_popGetLabel (jtab->key);
12872     //fprintf (stderr, "Creating jump table...\n");
12873
12874     // calculate offset into jump table (idx * sizeof (GOTO))
12875     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12876     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12877     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12878     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12879     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12880     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12881     pic16_emitpcode(POC_MOVWF , jt_offs);
12882
12883     // prepare PCLATx (set to first entry in jump table)
12884     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12885     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12886     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12887     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12888     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12889
12890     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12891     pic16_emitpcode(POC_ADDWF , jt_offs);
12892     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12893     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12894     emitSKPNC;
12895     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12896
12897     // release temporaries and prepare jump into table (new PCL --> WREG)
12898     pic16_emitpcode(POC_MOVFW , jt_offs);
12899     pic16_popReleaseTempReg (jt_offs_hi, 1);
12900     pic16_popReleaseTempReg (jt_offs, 0);
12901
12902     // jump into the table
12903     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12904
12905     pic16_emitpLabelFORCE(jtab->key);
12906 #endif
12907
12908     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12909 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12910
12911     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12912     /* now generate the jump labels */
12913     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12914          jtab = setNextItem(IC_JTLABELS(ic))) {
12915 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12916         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12917         
12918     }
12919     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12920
12921 }
12922
12923 /*-----------------------------------------------------------------*/
12924 /* genMixedOperation - gen code for operators between mixed types  */
12925 /*-----------------------------------------------------------------*/
12926 /*
12927   TSD - Written for the PIC port - but this unfortunately is buggy.
12928   This routine is good in that it is able to efficiently promote 
12929   types to different (larger) sizes. Unfortunately, the temporary
12930   variables that are optimized out by this routine are sometimes
12931   used in other places. So until I know how to really parse the 
12932   iCode tree, I'm going to not be using this routine :(.
12933 */
12934 static int genMixedOperation (iCode *ic)
12935 {
12936 #if 0
12937   operand *result = IC_RESULT(ic);
12938   sym_link *ctype = operandType(IC_LEFT(ic));
12939   operand *right = IC_RIGHT(ic);
12940   int ret = 0;
12941   int big,small;
12942   int offset;
12943
12944   iCode *nextic;
12945   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12946
12947   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12948
12949   nextic = ic->next;
12950   if(!nextic)
12951     return 0;
12952
12953   nextright = IC_RIGHT(nextic);
12954   nextleft  = IC_LEFT(nextic);
12955   nextresult = IC_RESULT(nextic);
12956
12957   pic16_aopOp(right,ic,FALSE);
12958   pic16_aopOp(result,ic,FALSE);
12959   pic16_aopOp(nextright,  nextic, FALSE);
12960   pic16_aopOp(nextleft,   nextic, FALSE);
12961   pic16_aopOp(nextresult, nextic, FALSE);
12962
12963   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12964
12965     operand *t = right;
12966     right = nextright;
12967     nextright = t; 
12968
12969     pic16_emitcode(";remove right +","");
12970
12971   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12972 /*
12973     operand *t = right;
12974     right = nextleft;
12975     nextleft = t; 
12976 */
12977     pic16_emitcode(";remove left +","");
12978   } else
12979     return 0;
12980
12981   big = AOP_SIZE(nextleft);
12982   small = AOP_SIZE(nextright);
12983
12984   switch(nextic->op) {
12985
12986   case '+':
12987     pic16_emitcode(";optimize a +","");
12988     /* if unsigned or not an integral type */
12989     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12990       pic16_emitcode(";add a bit to something","");
12991     } else {
12992
12993       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12994
12995       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12996         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12997         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12998       } else
12999         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
13000
13001       offset = 0;
13002       while(--big) {
13003
13004         offset++;
13005
13006         if(--small) {
13007           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13008             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13009             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13010           }
13011
13012           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13013           emitSKPNC;
13014           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13015                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
13016                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
13017           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13018           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
13019
13020         } else {
13021           pic16_emitcode("rlf","known_zero,w");
13022
13023           /*
13024             if right is signed
13025               btfsc  right,7
13026                addlw ff
13027           */
13028           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
13029             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
13030             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13031           } else {
13032             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
13033           }
13034         }
13035       }
13036       ret = 1;
13037     }
13038   }
13039   ret = 1;
13040
13041 release:
13042   pic16_freeAsmop(right,NULL,ic,TRUE);
13043   pic16_freeAsmop(result,NULL,ic,TRUE);
13044   pic16_freeAsmop(nextright,NULL,ic,TRUE);
13045   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
13046   if(ret)
13047     nextic->generated = 1;
13048
13049   return ret;
13050 #else
13051   return 0;
13052 #endif
13053 }
13054 /*-----------------------------------------------------------------*/
13055 /* genCast - gen code for casting                                  */
13056 /*-----------------------------------------------------------------*/
13057 static void genCast (iCode *ic)
13058 {
13059   operand *result = IC_RESULT(ic);
13060   sym_link *ctype = operandType(IC_LEFT(ic));
13061   sym_link *rtype = operandType(IC_RIGHT(ic));
13062   sym_link *restype = operandType(IC_RESULT(ic));
13063   operand *right = IC_RIGHT(ic);
13064   int size, offset ;
13065
13066
13067     FENTRY;
13068
13069         /* if they are equivalent then do nothing */
13070 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
13071 //              return ;
13072
13073         pic16_aopOp(result,ic,FALSE);
13074         pic16_aopOp(right,ic,FALSE) ;
13075
13076         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
13077
13078
13079         /* if the result is a bit */
13080         if (AOP_TYPE(result) == AOP_CRY) {
13081         
13082                 /* if the right size is a literal then
13083                  * we know what the value is */
13084                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13085
13086                 if (AOP_TYPE(right) == AOP_LIT) {
13087                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
13088                                 pic16_popGet(AOP(result),0));
13089
13090                         if (((int) operandLitValue(right))) 
13091                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
13092                                         AOP(result)->aopu.aop_dir,
13093                                         AOP(result)->aopu.aop_dir);
13094                         else
13095                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
13096                                         AOP(result)->aopu.aop_dir,
13097                                         AOP(result)->aopu.aop_dir);
13098                         goto release;
13099                 }
13100
13101                 /* the right is also a bit variable */
13102                 if (AOP_TYPE(right) == AOP_CRY) {
13103                         emitCLRC;
13104                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13105
13106                         pic16_emitcode("clrc","");
13107                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
13108                                 AOP(right)->aopu.aop_dir,
13109                                 AOP(right)->aopu.aop_dir);
13110                         pic16_aopPut(AOP(result),"c",0);
13111                         goto release ;
13112                 }
13113
13114                 /* we need to or */
13115                 if (AOP_TYPE(right) == AOP_REG) {
13116                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
13117                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
13118                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
13119                 }
13120                 pic16_toBoolean(right);
13121                 pic16_aopPut(AOP(result),"a",0);
13122                 goto release ;
13123         }
13124
13125         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
13126           int offset = 1;
13127
13128                 size = AOP_SIZE(result);
13129
13130                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13131
13132                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
13133                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
13134                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
13135
13136                 while (size--)
13137                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13138
13139                 goto release;
13140         }
13141
13142         if(IS_BITFIELD(getSpec(restype))
13143           && IS_BITFIELD(getSpec(rtype))) {
13144           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
13145         }
13146         
13147         /* port from pic14 to cope with generic pointers */
13148         if (PIC_IS_TAGGED(restype))
13149         {
13150           operand *result = IC_RESULT(ic);
13151           //operand *left = IC_LEFT(ic);
13152           operand *right = IC_RIGHT(ic);
13153           int tag = 0xff;
13154
13155           /* copy common part */
13156           int max, size = AOP_SIZE(result);
13157           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
13158           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13159
13160           max = size;
13161           while (size--)
13162           {
13163             pic16_mov2w (AOP(right), size);
13164             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
13165           } // while
13166
13167           /* upcast into generic pointer type? */
13168           if (IS_GENPTR(restype)
13169               && !PIC_IS_TAGGED(rtype)
13170               && (AOP_SIZE(result) > max))
13171           {
13172             /* determine appropriate tag for right */
13173             if (PIC_IS_DATA_PTR(rtype))
13174               tag = GPTR_TAG_DATA;
13175             else if (IS_CODEPTR(rtype))
13176               tag = GPTR_TAG_CODE;
13177             else if (PIC_IS_DATA_PTR(ctype)) {
13178               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
13179               tag = GPTR_TAG_DATA;
13180             } else if (IS_CODEPTR(ctype)) {
13181               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
13182               tag = GPTR_TAG_CODE;
13183             } else if (IS_PTR(rtype)) {
13184               PERFORM_ONCE(weirdcast,
13185               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assuming __data space\n", ic->filename, ic->lineno);
13186               );
13187               tag = GPTR_TAG_DATA;
13188             } else {
13189               PERFORM_ONCE(weirdcast,
13190               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assuming __data space\n", ic->filename, ic->lineno);
13191               );
13192               tag = GPTR_TAG_DATA;
13193             }
13194
13195             assert (AOP_SIZE(result) == 3);
13196             /* zero-extend address... */
13197             for (size = max; size < AOP_SIZE(result)-1; size++)
13198               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
13199             /* ...and add tag */
13200             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
13201           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
13202             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
13203             for (size = max; size < AOP_SIZE(result)-1; size++)
13204               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
13205             /* add __code tag */
13206             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
13207           } else if (AOP_SIZE(result) > max) {
13208             /* extend non-pointers */
13209             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
13210             pic16_addSign(result, max, 0);
13211           } // if
13212           goto release;
13213         }
13214
13215         /* if they are the same size : or less */
13216         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
13217
13218                 /* if they are in the same place */
13219                 if (pic16_sameRegs(AOP(right),AOP(result)))
13220                         goto release;
13221
13222                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13223 #if 0
13224                 if (IS_PTR_CONST(rtype))
13225 #else
13226                 if (IS_CODEPTR(rtype))
13227 #endif
13228                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
13229
13230 #if 0
13231                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
13232 #else
13233                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
13234 #endif
13235                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
13236
13237 #if 0
13238                 if(AOP_TYPE(right) == AOP_IMMD) {
13239                   pCodeOp *pcop0, *pcop1, *pcop2;
13240                   symbol *sym = OP_SYMBOL( right );
13241
13242                         size = AOP_SIZE(result);
13243                         /* low */
13244                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13245                         /* high */
13246                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13247                         /* upper */
13248                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13249         
13250                         if (size == 3) {
13251                                 pic16_emitpcode(POC_MOVLW, pcop0);
13252                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13253                                 pic16_emitpcode(POC_MOVLW, pcop1);
13254                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13255                                 pic16_emitpcode(POC_MOVLW, pcop2);
13256                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13257                         } else
13258                         if (size == 2) {
13259                                 pic16_emitpcode(POC_MOVLW, pcop0);
13260                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13261                                 pic16_emitpcode(POC_MOVLW, pcop1);
13262                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13263                         } else {
13264                                 pic16_emitpcode(POC_MOVLW, pcop0);
13265                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13266                         }
13267                 } else
13268 #endif
13269                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13270                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13271                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13272
13273                         if(AOP_SIZE(result) < 2) {
13274                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13275                         } else {
13276                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13277                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13278                         }
13279                 } else {
13280                         /* if they in different places then copy */
13281                         size = AOP_SIZE(result);
13282                         offset = 0 ;
13283                         while (size--) {
13284                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13285                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13286                                 offset++;
13287                         }
13288                 }
13289                 goto release;
13290         }
13291
13292         /* if the result is of type pointer */
13293         if (IS_PTR(ctype)) {
13294           int p_type;
13295           sym_link *type = operandType(right);
13296           sym_link *etype = getSpec(type);
13297
13298                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13299
13300                 /* pointer to generic pointer */
13301                 if (IS_GENPTR(ctype)) {
13302                   char *l = zero;
13303             
13304                         if (IS_PTR(type)) 
13305                                 p_type = DCL_TYPE(type);
13306                         else {
13307                 /* we have to go by the storage class */
13308                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13309
13310 /*              if (SPEC_OCLS(etype)->codesp )  */
13311 /*                  p_type = CPOINTER ;  */
13312 /*              else */
13313 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13314 /*                      p_type = FPOINTER ; */
13315 /*                  else */
13316 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13317 /*                          p_type = PPOINTER; */
13318 /*                      else */
13319 /*                          if (SPEC_OCLS(etype) == idata ) */
13320 /*                              p_type = IPOINTER ; */
13321 /*                          else */
13322 /*                              p_type = POINTER ; */
13323             }
13324                 
13325             /* the first two bytes are known */
13326       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13327             size = GPTRSIZE - 1; 
13328             offset = 0 ;
13329             while (size--) {
13330               if(offset < AOP_SIZE(right)) {
13331                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13332                 pic16_mov2f(AOP(result), AOP(right), offset);
13333 /*
13334                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13335                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13336                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13337                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13338                 } else { 
13339                   
13340                   pic16_aopPut(AOP(result),
13341                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13342                          offset);
13343                 }
13344 */
13345               } else 
13346                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13347               offset++;
13348             }
13349             /* the last byte depending on type */
13350             switch (p_type) {
13351             case IPOINTER:
13352             case POINTER:
13353             case FPOINTER:
13354                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13355                 break;
13356
13357             case CPOINTER:
13358                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13359                 break;
13360
13361             case PPOINTER:
13362               pic16_emitcode(";BUG!? ","%d",__LINE__);
13363                 l = "#0x03";
13364                 break;
13365
13366             case GPOINTER:
13367                 if (GPTRSIZE > AOP_SIZE(right)) {
13368                   // assume __data pointer... THIS MIGHT BE WRONG!
13369                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13370                 } else {
13371                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13372                 }
13373               break;
13374               
13375             default:
13376                 /* this should never happen */
13377                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13378                        "got unknown pointer type");
13379                 exit(1);
13380             }
13381             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13382             goto release ;
13383         }
13384         
13385         
13386         assert( 0 );
13387         /* just copy the pointers */
13388         size = AOP_SIZE(result);
13389         offset = 0 ;
13390         while (size--) {
13391             pic16_aopPut(AOP(result),
13392                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13393                    offset);
13394             offset++;
13395         }
13396         goto release ;
13397     }
13398     
13399
13400
13401     /* so we now know that the size of destination is greater
13402     than the size of the source.
13403     Now, if the next iCode is an operator then we might be
13404     able to optimize the operation without performing a cast.
13405     */
13406     if(genMixedOperation(ic))
13407       goto release;
13408
13409     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13410     
13411     /* we move to result for the size of source */
13412     size = AOP_SIZE(right);
13413     offset = 0 ;
13414
13415     while (size--) {
13416       if(!_G.resDirect)
13417         pic16_mov2f(AOP(result), AOP(right), offset);
13418       offset++;
13419     }
13420
13421     /* now depending on the sign of the destination */
13422     size = AOP_SIZE(result) - AOP_SIZE(right);
13423     /* if unsigned or not an integral type */
13424     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13425       while (size--)
13426         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13427     } else {
13428       /* we need to extend the sign :( */
13429
13430       if(size == 1) {
13431         /* Save one instruction of casting char to int */
13432         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13433         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13434         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13435       } else {
13436         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13437
13438         if(offset)
13439           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13440         else
13441           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13442         
13443         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13444
13445         while (size--)
13446           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13447       }
13448     }
13449
13450 release:
13451     pic16_freeAsmop(right,NULL,ic,TRUE);
13452     pic16_freeAsmop(result,NULL,ic,TRUE);
13453
13454 }
13455
13456 /*-----------------------------------------------------------------*/
13457 /* genDjnz - generate decrement & jump if not zero instrucion      */
13458 /*-----------------------------------------------------------------*/
13459 static int genDjnz (iCode *ic, iCode *ifx)
13460 {
13461     symbol *lbl, *lbl1;
13462     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13463
13464     if (!ifx)
13465         return 0;
13466     
13467     /* if the if condition has a false label
13468        then we cannot save */
13469     if (IC_FALSE(ifx))
13470         return 0;
13471
13472     /* if the minus is not of the form 
13473        a = a - 1 */
13474     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13475         !IS_OP_LITERAL(IC_RIGHT(ic)))
13476         return 0;
13477
13478     if (operandLitValue(IC_RIGHT(ic)) != 1)
13479         return 0;
13480
13481     /* if the size of this greater than one then no
13482        saving */
13483     if (getSize(operandType(IC_RESULT(ic))) > 1)
13484         return 0;
13485
13486     /* otherwise we can save BIG */
13487     lbl = newiTempLabel(NULL);
13488     lbl1= newiTempLabel(NULL);
13489
13490     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13491     
13492     if (IS_AOP_PREG(IC_RESULT(ic))) {
13493         pic16_emitcode("dec","%s",
13494                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13495         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13496         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13497     } else {    
13498
13499
13500       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13501       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13502
13503       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13504       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13505
13506     }
13507     
13508     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13509     ifx->generated = 1;
13510     return 1;
13511 }
13512
13513 /*-----------------------------------------------------------------*/
13514 /* genReceive - generate code for a receive iCode                  */
13515 /*-----------------------------------------------------------------*/
13516 static void genReceive (iCode *ic)
13517 {    
13518
13519   FENTRY;
13520
13521 #if 0
13522   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13523         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13524 #endif
13525 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13526
13527   if (isOperandInFarSpace(IC_RESULT(ic))
13528       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13529           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13530
13531     int size = getSize(operandType(IC_RESULT(ic)));
13532     int offset =  pic16_fReturnSizePic - size;
13533
13534       assert( 0 );
13535       while (size--) {
13536         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13537                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13538                       offset++;
13539         }
13540
13541       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13542
13543       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13544       size = AOP_SIZE(IC_RESULT(ic));
13545       offset = 0;
13546       while (size--) {
13547         pic16_emitcode ("pop","acc");
13548         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13549       }
13550   } else {
13551     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13552     _G.accInUse++;
13553     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13554     _G.accInUse--;
13555
13556     /* set pseudo stack pointer to where it should be - dw*/
13557     GpsuedoStkPtr = ic->parmBytes;
13558
13559     /* setting GpsuedoStkPtr has side effects here: */
13560     /* FIXME: What's the correct size of the return(ed) value?
13561      *        For now, assuming '4' as before... */
13562     assignResultValue(IC_RESULT(ic), 4, 0);
13563   }
13564
13565   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13566 }
13567
13568 /*-----------------------------------------------------------------*/
13569 /* genDummyRead - generate code for dummy read of volatiles        */
13570 /*-----------------------------------------------------------------*/
13571 static void
13572 genDummyRead (iCode * ic)
13573 {
13574   operand *op;
13575   int i;
13576
13577   op = IC_RIGHT(ic);
13578   if (op && IS_SYMOP(op)) {
13579     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13580       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13581       return;
13582     }
13583     pic16_aopOp (op, ic, FALSE);
13584     for (i=0; i < AOP_SIZE(op); i++) {
13585       // may need to protect this from the peepholer -- this is not nice but works...
13586       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13587       pic16_mov2w (AOP(op),i);
13588       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13589     } // for i
13590     pic16_freeAsmop (op, NULL, ic, TRUE);
13591   } else if (op) {
13592     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13593   } // if
13594 }
13595
13596 /*-----------------------------------------------------------------*/
13597 /* genpic16Code - generate code for pic16 based controllers        */
13598 /*-----------------------------------------------------------------*/
13599 /*
13600  * At this point, ralloc.c has gone through the iCode and attempted
13601  * to optimize in a way suitable for a PIC. Now we've got to generate
13602  * PIC instructions that correspond to the iCode.
13603  *
13604  * Once the instructions are generated, we'll pass through both the
13605  * peep hole optimizer and the pCode optimizer.
13606  *-----------------------------------------------------------------*/
13607
13608 void genpic16Code (iCode *lic)
13609 {
13610   iCode *ic;
13611   int cln = 0;
13612
13613     lineHead = lineCurr = NULL;
13614
13615     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13616     pic16_addpBlock(pb);
13617
13618 #if 0
13619     /* if debug information required */
13620     if (options.debug && currFunc) {
13621       if (currFunc) {
13622         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13623       }
13624     }
13625 #endif
13626
13627     for (ic = lic ; ic ; ic = ic->next ) {
13628
13629       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13630       if ( cln != ic->lineno ) {
13631         if ( options.debug ) {
13632           debugFile->writeCLine (ic);
13633         }
13634         
13635         if(!options.noCcodeInAsm) {
13636           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13637               printCLine(ic->filename, ic->lineno)));
13638         }
13639
13640         cln = ic->lineno ;
13641       }
13642         
13643       if(options.iCodeInAsm) {
13644         char *iLine;
13645
13646           /* insert here code to print iCode as comment */
13647           iLine = printILine(ic);
13648           pic16_emitpcomment("ic:%d: %s", ic->seq, iLine);
13649           dbuf_free(iLine);
13650       }
13651
13652       /* if the result is marked as
13653        * spilt and rematerializable or code for
13654        * this has already been generated then
13655        * do nothing */
13656       if (resultRemat(ic) || ic->generated ) 
13657         continue ;
13658         
13659       /* depending on the operation */
13660       switch (ic->op) {
13661         case '!' :
13662           pic16_genNot(ic);
13663           break;
13664             
13665         case '~' :
13666           pic16_genCpl(ic);
13667           break;
13668             
13669         case UNARYMINUS:
13670           genUminus (ic);
13671           break;
13672             
13673         case IPUSH:
13674           genIpush (ic);
13675           break;
13676             
13677         case IPOP:
13678           /* IPOP happens only when trying to restore a 
13679            * spilt live range, if there is an ifx statement
13680            * following this pop then the if statement might
13681            * be using some of the registers being popped which
13682            * would destroy the contents of the register so
13683            * we need to check for this condition and handle it */
13684            if (ic->next
13685              && ic->next->op == IFX
13686              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13687                genIfx (ic->next,ic);
13688           else
13689             genIpop (ic);
13690           break; 
13691             
13692         case CALL:
13693           genCall (ic);
13694           break;
13695             
13696         case PCALL:
13697           genPcall (ic);
13698           break;
13699             
13700         case FUNCTION:
13701           genFunction (ic);
13702           break;
13703             
13704         case ENDFUNCTION:
13705           genEndFunction (ic);
13706           break;
13707             
13708         case RETURN:
13709           genRet (ic);
13710           break;
13711             
13712         case LABEL:
13713           genLabel (ic);
13714           break;
13715             
13716         case GOTO:
13717           genGoto (ic);
13718           break;
13719             
13720         case '+' :
13721           pic16_genPlus (ic) ;
13722           break;
13723             
13724         case '-' :
13725           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13726             pic16_genMinus (ic);
13727           break;
13728
13729         case '*' :
13730           genMult (ic);
13731           break;
13732             
13733         case '/' :
13734           genDiv (ic) ;
13735           break;
13736             
13737         case '%' :
13738           genMod (ic);
13739           break;
13740             
13741         case '>' :
13742           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13743           break;
13744             
13745         case '<' :
13746           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13747           break;
13748             
13749         case LE_OP:
13750         case GE_OP:
13751         case NE_OP:
13752           /* note these two are xlated by algebraic equivalence
13753            * during parsing SDCC.y */
13754           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13755             "got '>=' or '<=' shouldn't have come here");
13756           break;
13757
13758         case EQ_OP:
13759           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13760           break;            
13761             
13762         case AND_OP:
13763           genAndOp (ic);
13764           break;
13765             
13766         case OR_OP:
13767           genOrOp (ic);
13768           break;
13769             
13770         case '^' :
13771           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13772           break;
13773             
13774         case '|' :
13775           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13776           break;
13777             
13778         case BITWISEAND:
13779           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13780           break;
13781             
13782         case INLINEASM:
13783           genInline (ic);
13784           break;
13785             
13786         case RRC:
13787           genRRC (ic);
13788           break;
13789             
13790         case RLC:
13791           genRLC (ic);
13792           break;
13793             
13794         case GETHBIT:
13795           genGetHbit (ic);
13796           break;
13797             
13798         case LEFT_OP:
13799           genLeftShift (ic);
13800           break;
13801             
13802         case RIGHT_OP:
13803           genRightShift (ic);
13804           break;
13805             
13806         case GET_VALUE_AT_ADDRESS:
13807           genPointerGet(ic);
13808           break;
13809             
13810         case '=' :
13811           if (POINTER_SET(ic))
13812             genPointerSet(ic);
13813           else
13814             genAssign(ic);
13815           break;
13816             
13817         case IFX:
13818           genIfx (ic,NULL);
13819           break;
13820             
13821         case ADDRESS_OF:
13822           genAddrOf (ic);
13823           break;
13824             
13825         case JUMPTABLE:
13826           genJumpTab (ic);
13827           break;
13828             
13829         case CAST:
13830           genCast (ic);
13831           break;
13832             
13833         case RECEIVE:
13834           genReceive(ic);
13835           break;
13836             
13837         case SEND:
13838           addSet(&_G.sendSet,ic);
13839           break;
13840
13841         case DUMMY_READ_VOLATILE:
13842           genDummyRead (ic);
13843           break;
13844
13845         default :
13846           ic = ic;
13847       }
13848     }
13849
13850
13851     /* now we are ready to call the
13852        peep hole optimizer */
13853     if (!options.nopeep)
13854       peepHole (&lineHead);
13855
13856     /* now do the actual printing */
13857     printLine (lineHead, codeOutBuf);
13858
13859 #ifdef PCODE_DEBUG
13860     DFPRINTF((stderr,"printing pBlock\n\n"));
13861     pic16_printpBlock(stdout,pb);
13862 #endif
13863
13864     return;
13865 }
13866