1b16d206a74b70399d21944942d8fe8dbe04dfab
[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
51 /* Set the following to 1 to enable the slower/bigger
52  * but more robust generic shifting routine (which also
53  * operates correctly with negative shift values). */
54 #define USE_GENERIC_SIGNED_SHIFT 1
55
56 /* Set the following to 1 to enable the new
57  * stripped down genCmp version.
58  * This version should be easier to understand,
59  * more reliable and (sigh) slighly slower. */
60 #define USE_SIMPLE_GENCMP 1
61
62 /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */
63 #define PIC_IS_DATA_PTR(x)      (IS_DATA_PTR(x) || IS_FARPTR(x))
64 #define PIC_IS_FARPTR(x)        (IS_DATA_PTR(x) || IS_FARPTR(x))
65 #define PIC_IS_TAGGED(x)        (IS_GENPTR(x) || IS_CODEPTR(x))
66 #define IS_DIRECT(op)           ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR))
67
68 /* If you change these, you also have to update the library files
69  * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */
70 #define GPTR_TAG_DATA   0x80
71 #define GPTR_TAG_EEPROM 0x40
72 #define GPTR_TAG_CODE   0x00    /* must be 0 becaue of UPPER(sym)==0 */
73
74 /* Wrapper to execute `code' at most once. */
75 #define PERFORM_ONCE(id,code)   do { static char id = 0; if (!id) { id = 1; code } } while (0)
76
77 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
78 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
79 void pic16_genMult8X8_8 (operand *, operand *,operand *);
80 void pic16_genMult16X16_16(operand *, operand *, operand *);
81 void pic16_genMult32X32_32(operand *, operand *, operand *);
82 pCode *pic16_AssembleLine(char *line, int peeps);
83 extern void pic16_printpBlock(FILE *of, pBlock *pb);
84 static asmop *newAsmop (short type);
85 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op);
86 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
87 static void mov2fp(pCodeOp *dst, asmop *src, int offset);
88 static pCodeOp *pic16_popRegFromIdx(int rIdx);
89
90 //static int aopIdx (asmop *aop, int offset);
91
92 int pic16_labelOffset=0;
93 extern int pic16_debug_verbose;
94 #if !(USE_GENERIC_SIGNED_SHIFT)
95 static int optimized_for_speed = 0;
96 #endif
97 /*
98   hack hack
99
100 */
101
102 extern set *externs;
103
104 /* max_key keeps track of the largest label number used in 
105    a function. This is then used to adjust the label offset
106    for the next function.
107 */
108 static int max_key=0;
109 static int GpsuedoStkPtr=0;
110
111 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
112
113 unsigned int pic16aopLiteral (value *val, int offset);
114 const char *pic16_AopType(short type);
115 static iCode *ifxForOp ( operand *op, iCode *ic );
116
117 void pic16_pushpCodeOp(pCodeOp *pcop);
118 void pic16_poppCodeOp(pCodeOp *pcop);
119
120 static bool is_LitOp(operand *op);
121 static bool is_LitAOp(asmop *aop);
122
123
124 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
125
126 /* set the following macro to 1 to enable passing the
127  * first byte of functions parameters via WREG */
128 #define USE_WREG_IN_FUNC_PARAMS 0
129
130
131 /* this is the down and dirty file with all kinds of 
132    kludgy & hacky stuff. This is what it is all about
133    CODE GENERATION for a specific MCU . some of the
134    routines may be reusable, will have to see */
135
136 static char *zero = "#0x00";
137 static char *one  = "#0x01";
138 //static char *spname = "sp";
139
140
141 /*
142  * Function return value policy (MSB-->LSB):
143  *  8 bits      -> WREG
144  * 16 bits      -> PRODL:WREG
145  * 24 bits      -> PRODH:PRODL:WREG
146  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
147  * >32 bits     -> on stack, and FSR0 points to the beginning
148  *
149  */
150  
151
152 char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" };
153 int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L };
154 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
155 static char **fReturn = fReturnpic16;
156
157 static char *accUse[] = {"WREG"};
158
159 //static short rbank = -1;
160
161 static struct {
162     short r0Pushed;
163     short r1Pushed;
164     short fsr0Pushed;
165     short accInUse;
166     short inLine;
167     short debugLine;
168     short nRegsSaved;
169     short ipushRegs;
170     set *sendSet;
171     set *stackRegSet;
172     int usefastretfie;
173     bitVect *fregsUsed;                 /* registers used in function */
174     bitVect *sregsAlloc;
175     set *sregsAllocSet;                 /* registers used to store stack variables */
176     int stack_lat;                      /* stack offset latency */
177     int resDirect;
178     int useWreg;                        /* flag when WREG is used to pass function parameter */
179 } _G;
180
181 extern int pic16_ptrRegReq ;
182 extern int pic16_nRegs;
183 extern FILE *codeOutFile;
184 //static void saverbank (int, iCode *,bool);
185
186 static lineNode *lineHead = NULL;
187 static lineNode *lineCurr = NULL;
188
189 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
190 0xE0, 0xC0, 0x80, 0x00};
191 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
192 0x07, 0x03, 0x01, 0x00};
193
194 static  pBlock *pb;
195
196 /*-----------------------------------------------------------------*/
197 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
198 /*                 exponent of 2 is returned, otherwise -1 is      */
199 /*                 returned.                                       */
200 /* note that this is similar to the function `powof2' in SDCCsymt  */
201 /* if(n == 2^y)                                                    */
202 /*   return y;                                                     */
203 /* return -1;                                                      */
204 /*-----------------------------------------------------------------*/
205 int pic16_my_powof2 (unsigned long num)
206 {
207   if(num) {
208     if( (num & (num-1)) == 0) {
209       int nshifts = -1;
210       while(num) {
211         num>>=1;
212         nshifts++;
213       }
214       return nshifts;
215     }
216   }
217
218   return -1;
219 }
220
221 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
222 {
223   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
224                        line_no,
225                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
226                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
227                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
228                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
229                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
230                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
231                        ((result) ? AOP_SIZE(result) : 0));
232 }
233
234 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
235 {
236
237   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
238                        line_no,
239                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
240                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
241                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
242                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
243                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
244                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
245
246 }
247
248 void pic16_emitpcomment (char *fmt, ...)
249 {
250     va_list ap;
251     char lb[INITIAL_INLINEASM];  
252     unsigned char *lbp = (unsigned char *)lb;
253
254     va_start(ap,fmt);   
255
256     lb[0] = ';';
257     vsprintf(lb+1,fmt,ap);
258
259     while (isspace(*lbp)) lbp++;
260
261     if (lbp && *lbp) 
262         lineCurr = (lineCurr ?
263                     connectLine(lineCurr,newLineNode(lb)) :
264                     (lineHead = newLineNode(lb)));
265     lineCurr->isInline = _G.inLine;
266     lineCurr->isDebug  = _G.debugLine;
267
268     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
269     va_end(ap);
270
271 //      fprintf(stderr, "%s\n", lb);
272 }
273
274 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
275 {
276     va_list ap;
277     char lb[INITIAL_INLINEASM];  
278     unsigned char *lbp = (unsigned char *)lb;
279
280     if(!pic16_debug_verbose)
281       return;
282
283     va_start(ap,fmt);   
284
285     if (inst && *inst) {
286         if (fmt && *fmt)
287             sprintf(lb,"%s\t",inst);
288         else
289             sprintf(lb,"%s",inst);
290         vsprintf(lb+(strlen(lb)),fmt,ap);
291     }  else
292         vsprintf(lb,fmt,ap);
293
294     while (isspace(*lbp)) lbp++;
295
296     if (lbp && *lbp) 
297         lineCurr = (lineCurr ?
298                     connectLine(lineCurr,newLineNode(lb)) :
299                     (lineHead = newLineNode(lb)));
300     lineCurr->isInline = _G.inLine;
301     lineCurr->isDebug  = _G.debugLine;
302
303     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
304     va_end(ap);
305
306 //      fprintf(stderr, "%s\n", lb);
307 }
308
309
310
311 void pic16_emitpLabel(int key)
312 {
313   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset));
314 }
315
316 void pic16_emitpLabelFORCE(int key)
317 {
318   pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset));
319 }
320
321 /* gen.h defines a macro pic16_emitpcode that allows for debug information to be inserted on demand
322  * NEVER call pic16_emitpcode_real directly, please... */
323 void pic16_emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
324 {
325
326   if(pcop)
327     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
328   else
329     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
330 }
331
332 void pic16_emitpinfo(INFO_TYPE itype, pCodeOp *pcop)
333 {
334   if(pcop)
335     pic16_addpCode2pBlock(pb, pic16_newpCodeInfo(itype, pcop));
336   else
337     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
338 }
339   
340 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
341 {
342
343   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
344
345 }
346
347
348 #if 1
349 #define pic16_emitcode  DEBUGpic16_emitcode
350 #else
351 /*-----------------------------------------------------------------*/
352 /* pic16_emitcode - writes the code into a file : for now it is simple    */
353 /*-----------------------------------------------------------------*/
354 void pic16_emitcode (char *inst,char *fmt, ...)
355 {
356     va_list ap;
357     char lb[INITIAL_INLINEASM];  
358     unsigned char *lbp = lb;
359
360     va_start(ap,fmt);   
361
362     if (inst && *inst) {
363         if (fmt && *fmt)
364             sprintf(lb,"%s\t",inst);
365         else
366             sprintf(lb,"%s",inst);
367         vsprintf(lb+(strlen(lb)),fmt,ap);
368     }  else
369         vsprintf(lb,fmt,ap);
370
371     while (isspace(*lbp)) lbp++;
372
373     if (lbp && *lbp) 
374         lineCurr = (lineCurr ?
375                     connectLine(lineCurr,newLineNode(lb)) :
376                     (lineHead = newLineNode(lb)));
377     lineCurr->isInline = _G.inLine;
378     lineCurr->isDebug  = _G.debugLine;
379
380 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
381
382 //    if(pic16_debug_verbose)
383 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
384
385     va_end(ap);
386 }
387 #endif
388
389
390 /*-----------------------------------------------------------------*/
391 /* pic16_emitDebuggerSymbol - associate the current code location  */
392 /*   with a debugger symbol                                        */
393 /*-----------------------------------------------------------------*/
394 void
395 pic16_emitDebuggerSymbol (char * debugSym)
396 {
397   _G.debugLine = 1;
398   pic16_emitcode (";", "%s ==.", debugSym);
399   _G.debugLine = 0;
400 }
401
402
403 /*-----------------------------------------------------------------*/
404 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
405 /*-----------------------------------------------------------------*/
406 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
407 {
408 //    bool r0iu = FALSE , r1iu = FALSE;
409 //    bool r0ou = FALSE , r1ou = FALSE;
410     bool fsr0iu = FALSE, fsr0ou;
411     bool fsr2iu = FALSE, fsr2ou;
412     
413     //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__,  __FUNCTION__, __LINE__, ic->op, result);
414
415     
416     fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2);
417     fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0);
418     
419     fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2);
420     fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0);
421
422     if(bitVectBitValue(ic->rUsed, IDX_WREG)) {
423         fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__);
424         DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__);
425     }
426
427     if(!fsr0iu && !fsr0ou) {
428         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0);
429         (*aopp)->type = AOP_FSR0;
430
431         //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__);
432         
433       return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0));
434     }
435
436 #if 0
437     /* no usage of FSR2 */
438     if(!fsr2iu && !fsr2ou) {
439         ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2);
440         (*aopp)->type = AOP_FSR2;
441
442       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2);
443     }
444 #endif
445         
446     /* now we know they both have usage */
447     /* if fsr0 not used in this instruction */
448     if (!fsr0iu) {
449         if (!_G.fsr0Pushed) {
450                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
451                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
452                 _G.fsr0Pushed++;
453         }
454
455         ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0);
456         (*aopp)->type = AOP_FSR0;
457
458 //      fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__);
459
460       return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0);
461     }
462         
463
464     fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__);
465     assert( 0 );
466
467     return NULL;
468 #if 0
469     /* the logic: if r0 & r1 used in the instruction
470     then we are in trouble otherwise */
471
472     /* first check if r0 & r1 are used by this
473     instruction, in which case we are in trouble */
474     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
475         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
476     {
477         goto endOfWorld;      
478     }
479
480     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
481     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
482
483     /* if no usage of r0 then return it */
484     if (!r0iu && !r0ou) {
485         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
486         (*aopp)->type = AOP_R0; 
487         
488         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
489     }
490
491     /* if no usage of r1 then return it */
492     if (!r1iu && !r1ou) {
493         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
494         (*aopp)->type = AOP_R1;
495
496         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
497     }    
498
499     /* now we know they both have usage */
500     /* if r0 not used in this instruction */
501     if (!r0iu) {
502         /* push it if not already pushed */
503         if (!_G.r0Pushed) {
504           //pic16_emitcode ("push","%s",
505           //          pic16_regWithIdx(R0_IDX)->dname);
506             _G.r0Pushed++ ;
507         }
508         
509         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
510         (*aopp)->type = AOP_R0;
511
512         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
513     }
514
515     /* if r1 not used then */
516
517     if (!r1iu) {
518         /* push it if not already pushed */
519         if (!_G.r1Pushed) {
520           //pic16_emitcode ("push","%s",
521           //          pic16_regWithIdx(R1_IDX)->dname);
522             _G.r1Pushed++ ;
523         }
524         
525         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
526         (*aopp)->type = AOP_R1;
527         return pic16_regWithIdx(R1_IDX);
528     }
529
530 endOfWorld :
531     /* I said end of world but not quite end of world yet */
532     /* if this is a result then we can push it on the stack*/
533     if (result) {
534         (*aopp)->type = AOP_STK;    
535         return NULL;
536     }
537
538     /* other wise this is true end of the world */
539     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
540            "getFreePtr should never reach here");
541     exit(0);
542 #endif
543 }
544
545 /*-----------------------------------------------------------------*/
546 /* newAsmop - creates a new asmOp                                  */
547 /*-----------------------------------------------------------------*/
548 static asmop *newAsmop (short type)
549 {
550     asmop *aop;
551
552     aop = Safe_calloc(1,sizeof(asmop));
553     aop->type = type;
554     return aop;
555 }
556
557 static void genSetDPTR(int n)
558 {
559     if (!n)
560     {
561         pic16_emitcode(";", "Select standard DPTR");
562         pic16_emitcode("mov", "dps, #0x00");
563     }
564     else
565     {
566         pic16_emitcode(";", "Select alternate DPTR");
567         pic16_emitcode("mov", "dps, #0x01");
568     }
569 }
570
571 /*-----------------------------------------------------------------*/
572 /* resolveIfx - converts an iCode ifx into a form more useful for  */
573 /*              generating code                                    */
574 /*-----------------------------------------------------------------*/
575 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
576 {
577   FENTRY2;
578   
579 //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
580
581   if(!resIfx) 
582     return;
583
584
585   resIfx->condition = 1;    /* assume that the ifx is true */
586   resIfx->generated = 0;    /* indicate that the ifx has not been used */
587
588   if(!ifx) {
589     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
590
591 #if 1
592     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
593                         __FUNCTION__,__LINE__,resIfx->lbl->key);
594 #endif
595
596   } else {
597     if(IC_TRUE(ifx)) {
598       resIfx->lbl = IC_TRUE(ifx);
599     } else {
600       resIfx->lbl = IC_FALSE(ifx);
601       resIfx->condition = 0;
602     }
603
604 #if 1
605     if(IC_TRUE(ifx)) 
606       DEBUGpic16_emitcode("; +++","ifx true is non-null");
607     else
608       DEBUGpic16_emitcode("; +++","ifx true is null");
609     if(IC_FALSE(ifx)) 
610       DEBUGpic16_emitcode("; +++","ifx false is non-null");
611     else
612       DEBUGpic16_emitcode("; +++","ifx false is null");
613 #endif
614   }
615
616   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,pic16_labelOffset);
617
618 }
619 #if 0
620 /*-----------------------------------------------------------------*/
621 /* pointerCode - returns the code for a pointer type               */
622 /*-----------------------------------------------------------------*/
623 static int pointerCode (sym_link *etype)
624 {
625
626     return PTR_TYPE(SPEC_OCLS(etype));
627
628 }
629 #endif
630
631 /*-----------------------------------------------------------------*/
632 /* aopForSym - for a true symbol                                   */
633 /*-----------------------------------------------------------------*/
634 static asmop *aopForSym (iCode *ic, operand *op, bool result)
635 {
636     symbol *sym=OP_SYMBOL(op);
637     asmop *aop;
638     memmap *space= SPEC_OCLS(sym->etype);
639
640     FENTRY2;
641     
642     _G.resDirect = 0;   /* clear flag that instructs the result is loaded directly from aopForSym */
643     
644 //    sym = OP_SYMBOL(op);
645
646     /* if already has one */
647     if (sym->aop) {
648             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
649         return sym->aop;
650     }
651
652 #if 0
653     /* if symbol was initially placed onStack then we must re-place it
654      * to direct memory, since pic16 does not have a specific stack */
655     if(sym->onStack) {
656         fprintf(stderr, "%s:%d symbol %s on stack\n", __FILE__, __LINE__, OP_SYMBOL(op)->name);
657     }
658 #endif
659
660
661 #if 0
662     if(sym->iaccess) {
663       if(space->paged) {
664         fprintf(stderr, "%s:%d symbol %s points to paged data\n", __FILE__, __LINE__, sym->name);
665
666         sym->aop = aop = newAsmop (AOP_PAGED);
667         aop->aopu.aop_dir = sym->rname ;
668         aop->size = getSize(sym->type);
669         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
670         pic16_allocDirReg( IC_LEFT(ic) );
671         return aop;
672       }
673       assert( 0 );
674     }
675 #endif
676     
677 #if 1
678     /* assign depending on the storage class */
679     /* if it is on the stack or indirectly addressable */
680     /* space we need to assign either r0 or r1 to it   */    
681     if (sym->onStack)   // || sym->iaccess)
682     {
683       pCodeOp *pcop[4];
684       int i;
685       
686         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
687                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
688         
689         /* acquire a temporary register -- it is saved in function */
690
691         sym->aop = aop = newAsmop(AOP_STA);
692         aop->aopu.stk.stk = sym->stack;
693         aop->size = getSize(sym->type);
694
695
696         DEBUGpic16_emitcode("; +++ ", "%s:%d\top = %s", __FILE__, __LINE__, pic16_decodeOp(ic->op));
697         if((ic->op == '=' /*|| ic->op == CAST*/) && IC_RESULT(ic) && AOP( IC_RESULT(ic) )
698           && (AOP_TYPE(IC_RESULT(ic)) == AOP_REG)) {
699 //          pic16_DumpAop("aopForSym", AOP( IC_RESULT(ic) ));
700           
701           for(i=0;i<aop->size;i++)
702             aop->aopu.stk.pop[i] = pcop[i] = pic16_popRegFromIdx( AOP(IC_RESULT(ic))->aopu.aop_reg[i]->rIdx);
703             _G.resDirect = 1;   /* notify that result will be loaded directly from aopForSym */
704         } else
705         if(1 && ic->op == SEND) {
706
707           /* if SEND do the send here */
708           _G.resDirect = 1;
709         } else {
710 //                debugf3("symbol `%s' level = %d / %d\n", sym->name, ic->level, ic->seq);
711           for(i=0;i<aop->size;i++) {
712             aop->aopu.stk.pop[i] = pcop[i] = pic16_popGetTempRegCond(_G.fregsUsed, _G.sregsAlloc, 0 );
713             _G.sregsAlloc = bitVectSetBit(_G.sregsAlloc, PCOR(pcop[i])->r->rIdx);
714           }
715         }
716
717
718 //        fprintf(stderr, "%s:%d\t%s\tsym size %d\n", __FILE__, __LINE__, __FUNCTION__, aop->size);
719
720 #if 1
721         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d stack = %d",__LINE__,sym->rname,aop->size, sym->stack);
722
723         // we do not need to load the value if it is to be defined...
724         if (result) return aop;
725
726         if(_G.accInUse) {
727                 pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
728         }
729         
730         for(i=0;i<aop->size;i++) {
731
732           /* initialise for stack access via frame pointer */
733           // operands on stack are accessible via "{FRAME POINTER} + index" with index
734           // starting at 2 for arguments and growing from 0 downwards for
735           // local variables (index == 0 is not assigned so we add one here)
736           {
737             int soffs = sym->stack;
738             if (soffs <= 0) {
739               assert (soffs < 0);
740               soffs++;
741             } // if
742
743             if(1 && ic->op == SEND) {
744               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + aop->size - i - 1 /*+ _G.stack_lat*/));
745               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
746                     pic16_popCopyReg( pic16_frame_plusw ),
747                     pic16_popCopyReg(pic16_stack_postdec )));
748             } else {
749               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
750               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
751                   pic16_popCopyReg( pic16_frame_plusw ), pcop[i]));
752             }
753           }
754         }
755         
756         if(_G.accInUse) {
757                 pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
758         }
759         
760         return (aop);
761 #endif
762
763 #if 0
764         /* now assign the address of the variable to 
765         the pointer register */
766         if (aop->type != AOP_STK) {
767
768             if (sym->onStack) {
769                     if ( _G.accInUse )
770                         pic16_emitcode("push","acc");
771
772                     pic16_emitcode("mov","a,_bp");
773                     pic16_emitcode("add","a,#0x%02x",
774                              ((sym->stack < 0) ?
775                               ((char)(sym->stack - _G.nRegsSaved )) :
776                               ((char)sym->stack)) & 0xff);
777                     pic16_emitcode("mov","%s,a",
778                              aop->aopu.aop_ptr->name);
779
780                     if ( _G.accInUse )
781                         pic16_emitcode("pop","acc");
782             } else
783                 pic16_emitcode("mov","%s,#%s",
784                          aop->aopu.aop_ptr->name,
785                          sym->rname);
786             aop->paged = space->paged;
787         } else
788             aop->aopu.aop_stk = sym->stack;
789         return aop;
790 #endif
791
792     }
793 #endif
794
795 #if 0
796     if (sym->onStack && options.stack10bit)
797     {
798         /* It's on the 10 bit stack, which is located in
799          * far data space.
800          */
801          
802       //DEBUGpic16_emitcode(";","%d",__LINE__);
803
804         if ( _G.accInUse )
805                 pic16_emitcode("push","acc");
806
807         pic16_emitcode("mov","a,_bp");
808         pic16_emitcode("add","a,#0x%02x",
809                  ((sym->stack < 0) ?
810                    ((char)(sym->stack - _G.nRegsSaved )) :
811                    ((char)sym->stack)) & 0xff);
812         
813         genSetDPTR(1);
814         pic16_emitcode ("mov","dpx1,#0x40");
815         pic16_emitcode ("mov","dph1,#0x00");
816         pic16_emitcode ("mov","dpl1, a");
817         genSetDPTR(0);
818         
819         if ( _G.accInUse )
820             pic16_emitcode("pop","acc");
821             
822         sym->aop = aop = newAsmop(AOP_DPTR2);
823         aop->size = getSize(sym->type); 
824         return aop;
825     }
826 #endif
827
828 #if 1
829     /* special case for a function */
830     if (IS_FUNC(sym->type)) {   
831         sym->aop = aop = newAsmop(AOP_PCODE);
832         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
833         aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
834         PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
835         PCOI(aop->aopu.pcop)->index = 0;
836         aop->size = FPTRSIZE; 
837         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
838         return aop;
839     }
840 #endif
841
842
843
844     //DEBUGpic16_emitcode(";","%d",__LINE__);
845     /* if in bit space */
846     if (IN_BITSPACE(space)) {
847         sym->aop = aop = newAsmop (AOP_CRY);
848         aop->aopu.aop_dir = sym->rname ;
849         aop->size = getSize(sym->type);
850         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
851         return aop;
852     }
853     /* if it is in direct space */
854     if (IN_DIRSPACE(space)) {
855                 if(!strcmp(sym->rname, "_WREG")) {
856                         sym->aop = aop = newAsmop (AOP_ACC);
857                         aop->size = getSize(sym->type);         /* should always be 1 */
858                         assert(aop->size == 1);
859                         DEBUGpic16_emitcode(";","%d sym->rname (AOP_ACC) = %s, size = %d",__LINE__,sym->rname,aop->size);
860                         return (aop);
861                 } else {
862                         sym->aop = aop = newAsmop (AOP_DIR);
863                 aop->aopu.aop_dir = sym->rname ;
864             aop->size = getSize(sym->type);
865                 DEBUGpic16_emitcode(";","%d sym->rname (AOP_DIR) = %s, size = %d",__LINE__,sym->rname,aop->size);
866                         pic16_allocDirReg( IC_LEFT(ic) );
867                         return (aop);
868                 }
869         }
870
871     if (IN_FARSPACE(space) && !IN_CODESPACE(space)) {
872         sym->aop = aop = newAsmop (AOP_DIR);
873         aop->aopu.aop_dir = sym->rname ;
874         aop->size = getSize(sym->type);
875         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
876         pic16_allocDirReg( IC_LEFT(ic) );
877         return aop;
878     }
879
880
881     /* only remaining is far space */
882     sym->aop = aop = newAsmop(AOP_PCODE);
883
884 /* change the next if to 1 to revert to good old immediate code */
885         if(IN_CODESPACE(space)) {
886                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
887                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
888                 PCOI(aop->aopu.pcop)->index = 0;
889         } else {
890                 /* try to allocate via direct register */
891                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset, op); // Patch 8
892 //              aop->size = getSize( sym->type );
893         }
894
895         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
896                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
897
898 #if 0
899         if(!pic16_allocDirReg (IC_LEFT(ic)))
900                 return NULL;
901 #endif
902
903         if(IN_DIRSPACE( space ))
904                 aop->size = PTRSIZE;
905         else if(IN_CODESPACE( space ) || IN_FARSPACE( space ))
906                 aop->size = FPTRSIZE;
907         else if(IC_LEFT(ic) && AOP(IC_LEFT(ic))) aop->size = AOP_SIZE( IC_LEFT(ic) );
908         else if(IC_RIGHT(ic) && AOP(IC_RIGHT(ic))) aop->size = AOP_SIZE( IC_RIGHT(ic) );
909         else if(sym->onStack) {
910                 aop->size = PTRSIZE;
911         } else {
912           if(SPEC_SCLS(sym->etype) == S_PDATA) {
913             fprintf(stderr, "%s: %d symbol in PDATA space\n", __FILE__, __LINE__);
914             aop->size = FPTRSIZE;
915           } else
916                 assert( 0 );
917         }
918
919     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
920
921     /* if it is in code space */
922     if (IN_CODESPACE(space))
923         aop->code = 1;
924
925     return aop;     
926 }
927
928 /*-----------------------------------------------------------------*/
929 /* aopForRemat - rematerialzes an object                           */
930 /*-----------------------------------------------------------------*/
931 static asmop *aopForRemat (operand *op, bool result) // x symbol *sym)
932 {
933   symbol *sym = OP_SYMBOL(op);
934   operand *refop;
935   iCode *ic = NULL, *oldic;
936   asmop *aop = newAsmop(AOP_PCODE);
937   int val = 0;
938   int offset = 0;
939   int viaimmd=0;
940
941     FENTRY2;
942     
943         ic = sym->rematiCode;
944
945         if(IS_OP_POINTER(op)) {
946                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
947         }
948
949 //    if(!result)               /* fixme-vr */
950         for (;;) {
951                 oldic = ic;
952
953 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
954         
955                 if (ic->op == '+') {
956                         val += (int) operandLitValue(IC_RIGHT(ic));
957                 } else if (ic->op == '-') {
958                         val -= (int) operandLitValue(IC_RIGHT(ic));
959                 } else
960                         break;
961                 
962                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
963         }
964
965         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
966         refop = IC_LEFT(ic);
967
968         if(!op->isaddr)viaimmd++; else viaimmd=0;
969                 
970 /* set the following if to 1 to revert to good old immediate code */
971         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(refop)))
972                 || viaimmd) {
973
974                 DEBUGpic16_emitcode(";", "%s:%d immediate, size: %d", __FILE__, __LINE__, getSize( sym->type ));
975
976                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
977
978 #if 0
979                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
980 #else
981                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
982 #endif
983
984                 PCOI(aop->aopu.pcop)->index = val;
985                 
986                 aop->size = getSize( sym->type );
987         } else {
988                 DEBUGpic16_emitcode(";", "%s:%d dir size: %d", __FILE__, __LINE__,  getSize( OP_SYMBOL( IC_LEFT(ic))->type));
989
990                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname,
991                                 getSize( OP_SYMBOL( IC_LEFT(ic))->type), val, op);
992
993                 aop->size = getSize( OP_SYMBOL( IC_LEFT(ic))->type );
994         }
995
996
997         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
998                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
999 #if 0
1000                 val, IS_PTR_CONST(operandType(op)));
1001 #else
1002                 val, IS_CODEPTR(operandType(op)));
1003 #endif
1004
1005 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
1006
1007         pic16_allocDirReg (IC_LEFT(ic));
1008
1009         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
1010                 aop->code = 1;
1011
1012   return aop;        
1013 }
1014
1015 #if 0
1016 static int aopIdx (asmop *aop, int offset)
1017 {
1018   if(!aop)
1019     return -1;
1020
1021   if(aop->type !=  AOP_REG)
1022     return -2;
1023         
1024   return aop->aopu.aop_reg[offset]->rIdx;
1025
1026 }
1027 #endif
1028
1029 /*-----------------------------------------------------------------*/
1030 /* regsInCommon - two operands have some registers in common       */
1031 /*-----------------------------------------------------------------*/
1032 static bool regsInCommon (operand *op1, operand *op2)
1033 {
1034     symbol *sym1, *sym2;
1035     int i;
1036
1037     /* if they have registers in common */
1038     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1039         return FALSE ;
1040
1041     sym1 = OP_SYMBOL(op1);
1042     sym2 = OP_SYMBOL(op2);
1043
1044     if (sym1->nRegs == 0 || sym2->nRegs == 0)
1045         return FALSE ;
1046
1047     for (i = 0 ; i < sym1->nRegs ; i++) {
1048         int j;
1049         if (!sym1->regs[i])
1050             continue ;
1051
1052         for (j = 0 ; j < sym2->nRegs ;j++ ) {
1053             if (!sym2->regs[j])
1054                 continue ;
1055
1056             if (sym2->regs[j] == sym1->regs[i])
1057                 return TRUE ;
1058         }
1059     }
1060
1061     return FALSE ;
1062 }
1063
1064 /*-----------------------------------------------------------------*/
1065 /* operandsEqu - equivalent                                        */
1066 /*-----------------------------------------------------------------*/
1067 static bool operandsEqu ( operand *op1, operand *op2)
1068 {
1069     symbol *sym1, *sym2;
1070
1071     /* if they not symbols */
1072     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
1073         return FALSE;
1074
1075     sym1 = OP_SYMBOL(op1);
1076     sym2 = OP_SYMBOL(op2);
1077
1078     /* if both are itemps & one is spilt
1079        and the other is not then false */
1080     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
1081         sym1->isspilt != sym2->isspilt )
1082         return FALSE ;
1083
1084     /* if they are the same */
1085     if (sym1 == sym2)
1086         return TRUE ;
1087
1088     if (sym1->rname[0] && sym2->rname[0]
1089         && strcmp (sym1->rname, sym2->rname) == 0)
1090         return TRUE;
1091
1092
1093     /* if left is a tmp & right is not */
1094     if (IS_ITEMP(op1)  && 
1095         !IS_ITEMP(op2) &&
1096         sym1->isspilt  &&
1097         (sym1->usl.spillLoc == sym2))
1098         return TRUE;
1099
1100     if (IS_ITEMP(op2)  && 
1101         !IS_ITEMP(op1) &&
1102         sym2->isspilt  &&
1103         sym1->level > 0 &&
1104         (sym2->usl.spillLoc == sym1))
1105         return TRUE ;
1106
1107     return FALSE ;
1108 }
1109
1110 /*-----------------------------------------------------------------*/
1111 /* pic16_sameRegs - two asmops have the same registers                   */
1112 /*-----------------------------------------------------------------*/
1113 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
1114 {
1115     int i;
1116
1117     if (aop1 == aop2)
1118         return TRUE ;
1119
1120     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s\n", __FUNCTION__,
1121                 pic16_AopType(aop1->type), pic16_AopType(aop2->type));
1122
1123     if(aop1->type == AOP_ACC && aop2->type == AOP_ACC)return TRUE;
1124
1125     if (aop1->type != AOP_REG ||
1126         aop2->type != AOP_REG )
1127         return FALSE ;
1128
1129     /* This is a bit too restrictive if one is a subset of the other...
1130     if (aop1->size != aop2->size )
1131         return FALSE ;
1132     */
1133
1134     for (i = 0 ; i < min(aop1->size, aop2->size) ; i++ ) {
1135 //        if(aop1->aopu.aop_reg[i]->type != aop2->aopu.aop_reg[i]->type)return FALSE;
1136
1137 //        if(aop1->aopu.aop_reg[i]->type == AOP_REG)
1138         if (strcmp(aop1->aopu.aop_reg[i]->name, aop2->aopu.aop_reg[i]->name ))
1139             return FALSE ;
1140     }
1141
1142     return TRUE ;
1143 }
1144
1145 bool pic16_sameRegsOfs(asmop *aop1, asmop *aop2, int offset)
1146 {
1147     DEBUGpic16_emitcode(";***", "%s aop1->type = %s\taop2->type = %s (offset = %d)\n", __FUNCTION__,
1148                 pic16_AopType(aop1->type), pic16_AopType(aop2->type), offset);
1149
1150     if(aop1 == aop2)return TRUE;
1151     if(aop1->type != AOP_REG || aop2->type != AOP_REG)return FALSE;
1152       
1153       if(strcmp(aop1->aopu.aop_reg[offset]->name, aop2->aopu.aop_reg[offset]->name))return FALSE;
1154     
1155   return TRUE;
1156 }
1157
1158
1159 /*-----------------------------------------------------------------*/
1160 /* pic16_aopOp - allocates an asmop for an operand  :                    */
1161 /*-----------------------------------------------------------------*/
1162 void pic16_aopOp (operand *op, iCode *ic, bool result)
1163 {
1164     asmop *aop;
1165     symbol *sym;
1166     int i;
1167
1168     if (!op)
1169         return ;
1170
1171     DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
1172
1173     /* if this a literal */
1174     if (IS_OP_LITERAL(op)) {
1175         op->aop = aop = newAsmop(AOP_LIT);
1176         aop->aopu.aop_lit = op->operand.valOperand;
1177         aop->size = getSize(operandType(op));
1178         return;
1179     }
1180
1181     {
1182       sym_link *type = operandType(op);
1183 #if 0
1184       if(IS_PTR_CONST(type))
1185 #else
1186       if(IS_CODEPTR(type))
1187 #endif
1188         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1189     }
1190
1191     /* if already has a asmop then continue */
1192     if (op->aop)
1193         return ;
1194
1195     /* if the underlying symbol has a aop */
1196     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
1197       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
1198         op->aop = OP_SYMBOL(op)->aop;
1199         return;
1200     }
1201
1202     /* if this is a true symbol */
1203     if (IS_TRUE_SYMOP(op)) {    
1204         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
1205       op->aop = aopForSym(ic, op, result);
1206       return ;
1207     }
1208
1209     /* this is a temporary : this has
1210     only four choices :
1211     a) register
1212     b) spillocation
1213     c) rematerialize 
1214     d) conditional   
1215     e) can be a return use only */
1216
1217     sym = OP_SYMBOL(op);
1218
1219     DEBUGpic16_emitcode("; ***", "%d: symbol name = %s, regType = %d", __LINE__, sym->name, sym->regType);
1220     /* if the type is a conditional */
1221     if (sym->regType == REG_CND) {
1222         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
1223         aop->size = 0;
1224         return;
1225     }
1226
1227     /* if it is spilt then two situations
1228     a) is rematerialize 
1229     b) has a spill location */
1230     if (sym->isspilt || sym->nRegs == 0) {
1231
1232 //      debugf3("symbol %s\tisspilt: %d\tnRegs: %d\n", sym->rname, sym->isspilt, sym->nRegs);
1233       DEBUGpic16_emitcode(";","%d",__LINE__);
1234         /* rematerialize it NOW */
1235         if (sym->remat) {
1236
1237             sym->aop = op->aop = aop = aopForRemat (op, result);
1238 //            aop->size = getSize(sym->type);
1239 //          DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
1240             return;
1241         }
1242
1243 #if 1
1244         if (sym->accuse) {
1245             int i;
1246             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
1247             aop->size = getSize(sym->type);
1248             for ( i = 0 ; i < 1 ; i++ ) {
1249                 aop->aopu.aop_str[i] = accUse[i];
1250 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
1251             }
1252             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
1253             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
1254             return;  
1255         }
1256 #endif
1257
1258 #if 1
1259         if (sym->ruonly) {
1260           /*
1261           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1262           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1263           //pic16_allocDirReg (IC_LEFT(ic));
1264           aop->size = getSize(sym->type);
1265           */
1266
1267           unsigned i;
1268
1269           aop = op->aop = sym->aop = newAsmop(AOP_REG);
1270           aop->size = getSize(sym->type);
1271           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
1272             aop->aopu.aop_reg[i] = PCOR(pic16_popRegFromIdx( fReturnIdx[i] ))->r;
1273
1274           DEBUGpic16_emitcode(";","%d",__LINE__);
1275           return;
1276         }
1277 #endif
1278         /* else spill location  */
1279         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1280             /* force a new aop if sizes differ */
1281             sym->usl.spillLoc->aop = NULL;
1282         }
1283
1284 #if 0
1285         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1286                             __FUNCTION__,__LINE__,
1287                             sym->usl.spillLoc->rname,
1288                             sym->rname, sym->usl.spillLoc->offset);
1289 #endif
1290
1291         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1292         if (sym->usl.spillLoc && sym->usl.spillLoc->rname) {
1293           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1294           aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1295                                                   getSize(sym->type), 
1296                                                   sym->usl.spillLoc->offset, op);
1297         } else if (getSize(sym->type) <= 1) {
1298           //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type));
1299           pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__);
1300           assert (getSize(sym->type) <= 1);
1301           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1302           aop->aopu.pcop = pic16_popCopyReg (&pic16_pc_wreg);
1303         } else {
1304           /* We need some kind of dummy area for getSize(sym->type) byte,
1305            * use WREG for all storage locations.
1306            * XXX: This only works if we are implementing a `dummy read',
1307            *      the stored value will not be retrievable...
1308            *      See #1503234 for a case requiring this. */
1309           sym->aop = op->aop = aop = newAsmop(AOP_REG);
1310           aop->size = getSize(sym->type);
1311           for ( i = 0 ; i < aop->size ;i++)
1312             aop->aopu.aop_reg[i] = pic16_pc_wreg.r;
1313         }
1314         aop->size = getSize(sym->type);
1315
1316         return;
1317     }
1318
1319     {
1320       sym_link *type = operandType(op);
1321 #if 0
1322       if(IS_PTR_CONST(type)) 
1323 #else
1324       if(IS_CODEPTR(type)) 
1325 #endif
1326         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1327     }
1328
1329     /* must be in a register */
1330     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1331     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1332     aop->size = sym->nRegs;
1333     for ( i = 0 ; i < sym->nRegs ;i++)
1334         aop->aopu.aop_reg[i] = sym->regs[i];
1335 }
1336
1337 /*-----------------------------------------------------------------*/
1338 /* pic16_freeAsmop - free up the asmop given to an operand               */
1339 /*----------------------------------------------------------------*/
1340 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1341 {   
1342     asmop *aop ;
1343
1344     if (!op)
1345         aop = aaop;
1346     else 
1347         aop = op->aop;
1348
1349     if (!aop)
1350         return ;
1351
1352     if (aop->freed)
1353         goto dealloc; 
1354
1355     aop->freed = 1;
1356
1357     /* depending on the asmop type only three cases need work AOP_RO
1358        , AOP_R1 && AOP_STK */
1359 #if 1
1360     switch (aop->type) {
1361         case AOP_FSR0 :
1362             if (_G.fsr0Pushed ) {
1363                 if (pop) {
1364                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) );
1365                     pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) );
1366 //                    pic16_emitcode ("pop","ar0");
1367                     _G.fsr0Pushed--;
1368                 }
1369             }
1370             bitVectUnSetBit(ic->rUsed,IDX_FSR0);
1371             break;
1372
1373         case AOP_FSR2 :
1374             bitVectUnSetBit(ic->rUsed,IDX_FSR2);
1375             break;
1376
1377         case AOP_R0 :
1378             if (_G.r0Pushed ) {
1379                 if (pop) {
1380                     pic16_emitcode ("pop","ar0");     
1381                     _G.r0Pushed--;
1382                 }
1383             }
1384             bitVectUnSetBit(ic->rUsed,R0_IDX);
1385             break;
1386
1387         case AOP_R1 :
1388             if (_G.r1Pushed ) {
1389                 if (pop) {
1390                     pic16_emitcode ("pop","ar1");
1391                     _G.r1Pushed--;
1392                 }
1393             }
1394             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1395             break;
1396
1397         case AOP_STA:
1398           {
1399             int i;
1400
1401               /* we must store the result on stack */
1402               if((op == IC_RESULT(ic)) && RESULTONSTA(ic)) {
1403                 // operands on stack are accessible via "FSR2 + index" with index
1404                 // starting at 2 for arguments and growing from 0 downwards for
1405                 // local variables (index == 0 is not assigned so we add one here)
1406                 int soffs = OP_SYMBOL(IC_RESULT(ic))->stack;
1407                 if (soffs <= 0) {
1408                   assert (soffs < 0);
1409                   soffs++;
1410                 } // if
1411                 if(_G.accInUse)pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1412                 for(i=0;i<aop->size;i++) {
1413                   /* initialise for stack access via frame pointer */
1414                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(soffs + i /*+ _G.stack_lat*/));
1415                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1416                         aop->aopu.stk.pop[i], pic16_popCopyReg(pic16_frame_plusw)));
1417                 }
1418         
1419                 if(_G.accInUse)pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_wreg) );
1420               }
1421
1422               if(!_G.resDirect) {
1423                 for(i=0;i<aop->size;i++) {
1424                   PCOR(aop->aopu.stk.pop[i] )->r->isFree = 1;
1425
1426                   if(bitVectBitValue(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx)) {
1427                       bitVectUnSetBit(_G.sregsAlloc, PCOR(aop->aopu.stk.pop[i])->r->rIdx);
1428 //                      pic16_popReleaseTempReg(aop->aopu.stk.pop[i], 0);
1429                   }
1430                 }
1431                 
1432                 {
1433                   regs *sr;
1434                   
1435                     _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
1436                     for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setFirstItem(_G.sregsAllocSet)) {
1437                       pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
1438                       deleteSetItem( &_G.sregsAllocSet, sr );
1439                     }
1440                 }
1441               }
1442               _G.resDirect = 0;
1443           }
1444           break;
1445 #if 0
1446         case AOP_STK :
1447         {
1448             int sz = aop->size;    
1449             int stk = aop->aopu.aop_stk + aop->size;
1450             bitVectUnSetBit(ic->rUsed,R0_IDX);
1451             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1452
1453             getFreePtr(ic,&aop,FALSE);
1454             
1455             if (options.stack10bit)
1456             {
1457                 /* I'm not sure what to do here yet... */
1458                 /* #STUB */
1459                 fprintf(stderr, 
1460                         "*** Warning: probably generating bad code for "
1461                         "10 bit stack mode.\n");
1462             }
1463             
1464             if (stk) {
1465                 pic16_emitcode ("mov","a,_bp");
1466                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1467                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1468             } else {
1469                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1470             }
1471
1472             while (sz--) {
1473                 pic16_emitcode("pop","acc");
1474                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1475                 if (!sz) break;
1476                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1477             }
1478             op->aop = aop;
1479             pic16_freeAsmop(op,NULL,ic,TRUE);
1480             if (_G.r0Pushed) {
1481                 pic16_emitcode("pop","ar0");
1482                 _G.r0Pushed--;
1483             }
1484
1485             if (_G.r1Pushed) {
1486                 pic16_emitcode("pop","ar1");
1487                 _G.r1Pushed--;
1488             }       
1489         }
1490 #endif
1491
1492     }
1493 #endif
1494
1495 dealloc:
1496     /* all other cases just dealloc */
1497     if (op ) {
1498         op->aop = NULL;
1499         if (IS_SYMOP(op)) {
1500             OP_SYMBOL(op)->aop = NULL;    
1501             /* if the symbol has a spill */
1502             if (SPIL_LOC(op))
1503                 SPIL_LOC(op)->aop = NULL;
1504         }
1505     }
1506 }
1507
1508 /*-----------------------------------------------------------------*/
1509 /* pic16_aopGet - for fetching value of the aop                          */
1510 /*-----------------------------------------------------------------*/
1511 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1512 {
1513     char *s = buffer ;
1514     char *rs;
1515
1516     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1517
1518     /* offset is greater than size then zero */
1519     if (offset > (aop->size - 1) &&
1520         aop->type != AOP_LIT)
1521         return zero;
1522
1523     /* depending on type */
1524     switch (aop->type) {
1525
1526     case AOP_FSR0:
1527     case AOP_FSR2:
1528       sprintf(s, "%s", aop->aopu.aop_ptr->name);
1529       rs = Safe_calloc(1, strlen(s)+1);
1530       strcpy(rs, s);
1531       return (rs);
1532       
1533 #if 0
1534       /* if we need to increment it */
1535       while (offset > aop->coff)
1536         {
1537           emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1538           aop->coff++;
1539         }
1540
1541       while (offset < aop->coff)
1542         {
1543           emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1544           aop->coff--;
1545         }
1546       aop->coff = offset;
1547       if (aop->paged)
1548         {
1549           emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1550           return (dname ? "acc" : "a");
1551         }
1552       sprintf (s, "@%s", aop->aopu.aop_ptr->name);
1553       rs = Safe_calloc (1, strlen (s) + 1);
1554       strcpy (rs, s);
1555       return rs;
1556 #endif
1557
1558         
1559     case AOP_IMMD:
1560         if (bit16) 
1561             sprintf (s,"%s",aop->aopu.aop_immd);
1562         else
1563             if (offset) 
1564                 sprintf(s,"(%s >> %d)",
1565                         aop->aopu.aop_immd,
1566                         offset*8);
1567             else
1568                 sprintf(s,"%s",
1569                         aop->aopu.aop_immd);
1570         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1571         rs = Safe_calloc(1,strlen(s)+1);
1572         strcpy(rs,s);   
1573         return rs;
1574         
1575     case AOP_DIR:
1576       if (offset) {
1577         sprintf(s,"(%s + %d)",
1578                 aop->aopu.aop_dir,
1579                 offset);
1580         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1581       } else
1582             sprintf(s,"%s",aop->aopu.aop_dir);
1583         rs = Safe_calloc(1,strlen(s)+1);
1584         strcpy(rs,s);   
1585         return rs;
1586         
1587     case AOP_REG:
1588       return aop->aopu.aop_reg[offset]->name;
1589         
1590     case AOP_CRY:
1591       return aop->aopu.aop_dir;
1592         
1593     case AOP_ACC:
1594         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d\toffset: %d",__LINE__, offset);
1595 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1596 //        assert( 0 );
1597 //      return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1598         rs = Safe_strdup("WREG");
1599         return (rs);
1600
1601     case AOP_LIT:
1602         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1603         rs = Safe_calloc(1,strlen(s)+1);
1604         strcpy(rs,s);   
1605         return rs;
1606         
1607     case AOP_STR:
1608         aop->coff = offset ;
1609
1610 //      if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1611 //          dname)
1612 //          return "acc";
1613         if(!strcmp(aop->aopu.aop_str[offset], "WREG")) {
1614           aop->type = AOP_ACC;
1615           return Safe_strdup("_WREG");
1616         }
1617         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1618         
1619         return aop->aopu.aop_str[offset];
1620         
1621     case AOP_PCODE:
1622       {
1623         pCodeOp *pcop = aop->aopu.pcop;
1624         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1625         if(pcop->name) {
1626           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1627           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1628           if (offset) {
1629             sprintf(s,"(%s + %d)", pic16_get_op (pcop, NULL, 0), offset);
1630           } else {
1631             sprintf(s,"%s", pic16_get_op (pcop, NULL, 0));
1632           }
1633         } else
1634           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1635
1636       }
1637       rs = Safe_calloc(1,strlen(s)+1);
1638       strcpy(rs,s);   
1639       return rs;
1640
1641 #if 0
1642     case AOP_PAGED:
1643       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1644       if (offset) {
1645         sprintf(s,"(%s + %d)",
1646                 aop->aopu.aop_dir,
1647                 offset);
1648       } else
1649             sprintf(s,"%s",aop->aopu.aop_dir);
1650       DEBUGpic16_emitcode(";","oops AOP_PAGED did this %s\n",s);
1651       rs = Safe_calloc(1,strlen(s)+1);
1652       strcpy(rs,s);   
1653       return rs;
1654 #endif
1655
1656     case AOP_STA:
1657         rs = Safe_strdup(PCOR(aop->aopu.stk.pop[offset])->r->name);
1658         return (rs);
1659         
1660     case AOP_STK:
1661 //        pCodeOp *pcop = aop->aop
1662         break;
1663
1664     }
1665
1666     fprintf(stderr, "%s:%d unsupported aop->type: %s\n", __FILE__, __LINE__, pic16_AopType(aop->type));
1667     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1668            "aopget got unsupported aop->type");
1669     exit(0);
1670 }
1671
1672
1673
1674 /* lock has the following meaning: When allocating temporary registers
1675  * for stack variables storage, the value of the temporary register is
1676  * saved on stack. Its value is restored at the end. This procedure is
1677  * done via calls to pic16_aopOp and pic16_freeAsmop functions. There is
1678  * a possibility that before a call to pic16_aopOp, a temporary register
1679  * is allocated for a while and it is freed after some time, this will
1680  * mess the stack and values will not be restored properly. So use lock=1
1681  * to allocate temporary registers used internally by the programmer, and
1682  * lock=0 to allocate registers for stack use. lock=1 will emit a warning
1683  * to inform the compiler developer about a possible bug. This is an internal
1684  * feature for developing the compiler -- VR */
1685  
1686 int _TempReg_lock = 0;
1687 /*-----------------------------------------------------------------*/
1688 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1689 /*-----------------------------------------------------------------*/
1690 pCodeOp *pic16_popGetTempReg(int lock)
1691 {
1692   pCodeOp *pcop=NULL;
1693   symbol *cfunc;
1694
1695 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1696     if(_TempReg_lock) {
1697 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1698     }
1699     
1700     _TempReg_lock += lock;
1701     
1702     cfunc = currFunc;
1703     currFunc = NULL;
1704
1705 #if 0
1706         {
1707           regs *rr;
1708           int i;
1709
1710                 /* this code might seem better but it does the *same* job with
1711                  * the old code, it all depends on ralloc.c to get a free/unused
1712                  * register */
1713          
1714                 i=0;
1715                 while(i < pic16_nRegs) {
1716                         rr = pic16_typeRegWithIdx(i, REG_GPR, 0);
1717                         fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr);
1718                         if((!rr || (rr && rr->isFree))
1719                                 && !bitVectBitValue(cfunc->regsUsed, i)) {
1720                                 pcop = pic16_newpCodeOpReg( i );
1721                                 PCOR(pcop)->r->wasUsed = 1;
1722                                 PCOR(pcop)->r->isFree = 0;
1723                                 break;
1724                         }
1725                         i++;
1726                 }
1727
1728                 if(pcop) {
1729                         pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1730                 }
1731         }
1732 #else
1733     pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1734     if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1735       PCOR(pcop)->r->wasUsed=1;
1736       PCOR(pcop)->r->isFree=0;
1737
1738       /* push value on stack */
1739       pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1740     }
1741 #endif
1742
1743     currFunc = cfunc;
1744
1745   return pcop;
1746 }
1747
1748 /*-----------------------------------------------------------------*/
1749 /* pic16_popGetTempRegCond - create a new temporary pCodeOp which  */
1750 /*                           is not part of f, but don't save if   */
1751 /*                           inside v                              */
1752 /*-----------------------------------------------------------------*/
1753 pCodeOp *pic16_popGetTempRegCond(bitVect *f, bitVect *v, int lock)
1754 {
1755   pCodeOp *pcop=NULL;
1756   symbol *cfunc;
1757   int i;
1758
1759 //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1760
1761     if(_TempReg_lock) {
1762 //      werror(W_POSSBUG2, __FILE__, __LINE__);
1763     }
1764
1765     _TempReg_lock += lock;
1766
1767     cfunc = currFunc;
1768     currFunc = NULL;
1769
1770     i = bitVectFirstBit(f);
1771     while(i < 128) {
1772
1773       /* bypass registers that are used by function */
1774       if(!bitVectBitValue(f, i)) {
1775       
1776         /* bypass registers that are already allocated for stack access */
1777         if(!bitVectBitValue(v, i))  {
1778         
1779 //          debugf("getting register rIdx = %d\n", i);
1780           /* ok, get the operand */
1781           pcop = pic16_newpCodeOpReg( i );
1782     
1783           /* should never by NULL */
1784           assert( pcop != NULL );
1785
1786           
1787           /* sanity check */
1788           if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1789             int found=0;
1790             
1791               PCOR(pcop)->r->wasUsed=1;
1792               PCOR(pcop)->r->isFree=0;
1793
1794
1795               {
1796                 regs *sr;
1797               
1798                   for(sr=setFirstItem(_G.sregsAllocSet);sr;sr=setNextItem(_G.sregsAllocSet)) {
1799
1800                     if(sr->rIdx == PCOR(pcop)->r->rIdx) {
1801                       /* already used in previous steps, break */
1802                       found=1;          
1803                       break;
1804                     }
1805                   }
1806               }
1807
1808               /* caller takes care of the following */
1809 //              bitVectSetBit(v, i);
1810
1811               if(!found) {
1812                 /* push value on stack */
1813                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1814                 addSet(&_G.sregsAllocSet, PCOR(pcop)->r);
1815               }
1816           
1817             break;
1818           }
1819         }
1820       }
1821       i++;
1822     }
1823
1824     currFunc = cfunc;
1825
1826   return pcop;
1827 }
1828
1829
1830 /*-----------------------------------------------------------------*/
1831 /* pic16_popReleaseTempReg - create a new temporary pCodeOp                  */
1832 /*-----------------------------------------------------------------*/
1833 void pic16_popReleaseTempReg(pCodeOp *pcop, int lock)
1834 {
1835   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1836
1837   _TempReg_lock -= lock;
1838
1839   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1840     PCOR(pcop)->r->isFree = 1;
1841
1842     pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1843   }
1844 }
1845 /*-----------------------------------------------------------------*/
1846 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1847 /*-----------------------------------------------------------------*/
1848 pCodeOp *pic16_popGetLabel(int key)
1849 {
1850
1851   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, pic16_labelOffset);
1852
1853   if(key>max_key)
1854     max_key = key;
1855
1856   return pic16_newpCodeOpLabel(NULL,key+100+pic16_labelOffset);
1857 }
1858
1859 /*-----------------------------------------------------------------*/
1860 /* pic16_popCopyReg - copy a pcode operator                              */
1861 /*-----------------------------------------------------------------*/
1862 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1863 {
1864   pCodeOpReg *pcor;
1865
1866   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1867   memcpy (pcor, pc, sizeof (pCodeOpReg));
1868   pcor->r->wasUsed = 1;
1869   
1870   //pcor->pcop.type = pc->pcop.type;
1871   if(pc->pcop.name) {
1872     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1873       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1874   } else
1875     pcor->pcop.name = NULL;
1876
1877   //pcor->r = pc->r;
1878   //pcor->rIdx = pc->rIdx;
1879   //pcor->r->wasUsed=1;
1880   //pcor->instance = pc->instance;
1881
1882 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1883
1884   return PCOP(pcor);
1885 }
1886
1887 /*-----------------------------------------------------------------*/
1888 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1889 /*-----------------------------------------------------------------*/
1890 pCodeOp *pic16_popGetLit(int lit)
1891 {
1892   return pic16_newpCodeOpLit(lit);
1893 }
1894
1895 /* Allow for 12 bit literals (LFSR x, <here!>). */
1896 pCodeOp *pic16_popGetLit12(int lit)
1897 {
1898   return pic16_newpCodeOpLit12(lit);
1899 }
1900
1901 /*-----------------------------------------------------------------*/
1902 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1903 /*-----------------------------------------------------------------*/
1904 pCodeOp *pic16_popGetLit2(int lit, pCodeOp *arg2)
1905 {
1906   return pic16_newpCodeOpLit2(lit, arg2);
1907 }
1908
1909
1910 /*-----------------------------------------------------------------*/
1911 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1912 /*-----------------------------------------------------------------*/
1913 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1914 {
1915   return pic16_newpCodeOpImmd(name, offset,index, 0);
1916 }
1917
1918
1919 /*-----------------------------------------------------------------*/
1920 /* pic16_popGet - asm operator to pcode operator conversion              */
1921 /*-----------------------------------------------------------------*/
1922 pCodeOp *pic16_popGetWithString(char *str)
1923 {
1924   pCodeOp *pcop;
1925
1926
1927   if(!str) {
1928     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1929     exit (1);
1930   }
1931
1932   pcop = pic16_newpCodeOp(str,PO_STR);
1933
1934   return pcop;
1935 }
1936
1937 /*-----------------------------------------------------------------*/
1938 /* pic16_popRegFromString -                                        */
1939 /*-----------------------------------------------------------------*/
1940 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op)
1941 {
1942
1943   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1944   pcop->type = PO_DIR;
1945
1946   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1947   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1948
1949   if(!str)
1950     str = "BAD_STRING";
1951
1952   pcop->name = Safe_calloc(1,strlen(str)+1);
1953   strcpy(pcop->name,str);
1954
1955   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1956
1957   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1958 //  PCOR(pcop)->r->wasUsed = 1;
1959
1960   /* make sure that register doesn't exist,
1961    * and operand isn't NULL
1962    * and symbol isn't in codespace (codespace symbols are handled elsewhere) */
1963   if((PCOR(pcop)->r == NULL) 
1964     && (op)
1965     && !IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
1966 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1967 //              __FUNCTION__, __LINE__, str, size, offset);
1968
1969     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size, op);
1970     //fprintf(stderr, "%s:%d: WARNING: need to allocate new register by name -> %s\n", __FILE__, __LINE__, str);
1971
1972   }
1973   PCOR(pcop)->instance = offset;
1974
1975   return pcop;
1976 }
1977
1978 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1979 {
1980   pCodeOp *pcop;
1981
1982 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1983 //      fprintf(stderr, "%s:%d rIdx = 0x%0x\n", __FUNCTION__, __LINE__, rIdx);
1984         
1985         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1986         PCOR(pcop)->rIdx = rIdx;
1987         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1988         if(!PCOR(pcop)->r)
1989                 PCOR(pcop)->r = pic16_allocWithIdx(rIdx);
1990                 
1991         PCOR(pcop)->r->isFree = 0;
1992         PCOR(pcop)->r->wasUsed = 1;
1993
1994         pcop->type = PCOR(pcop)->r->pc_type;
1995
1996   return pcop;
1997 }
1998
1999 /*---------------------------------------------------------------------------------*/
2000 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
2001 /*                 VR 030601                                                       */
2002 /*---------------------------------------------------------------------------------*/
2003 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
2004 {
2005   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2006         pic16_popGet(aop_src, offset), pic16_popGet(aop_dst, offset));
2007   return PCOP(pcop2);
2008 }
2009
2010
2011
2012 /*--------------------------------------------------------------------------------.-*/
2013 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
2014 /*                  VR 030601 , adapted by Hans Dorn                                */
2015 /*--------------------------------------------------------------------------------.-*/
2016 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
2017 {
2018   pCodeOp2 *pcop2;
2019   pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(src, dst);
2020   return PCOP(pcop2);
2021 }
2022
2023 /*---------------------------------------------------------------------------------*/
2024 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
2025 /*                     movff instruction                                           */
2026 /*---------------------------------------------------------------------------------*/
2027 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
2028 {
2029   pCodeOp2 *pcop2 = (pCodeOp2 *)pic16_newpCodeOp2(
2030         pic16_popCopyReg(src), pic16_popCopyReg(dst) );
2031
2032   return PCOP(pcop2);
2033 }
2034
2035
2036 /*-----------------------------------------------------------------*/
2037 /* pic16_popGet - asm operator to pcode operator conversion              */
2038 /*-----------------------------------------------------------------*/
2039 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
2040 {
2041 //  char *s = buffer ;
2042 //  char *rs;
2043   pCodeOp *pcop;
2044
2045     FENTRY2;
2046     
2047       /* offset is greater than size then zero */
2048
2049 //    if (offset > (aop->size - 1) &&
2050 //        aop->type != AOP_LIT)
2051 //      return NULL;  //zero;
2052
2053     /* depending on type */
2054     switch (aop->type) {
2055                 case AOP_R0:
2056                 case AOP_R1:
2057                 case AOP_DPTR:
2058                 case AOP_DPTR2:
2059                         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
2060                         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
2061                         assert( 0 );
2062                         return NULL;
2063
2064                 case AOP_FSR0:
2065                 case AOP_FSR2:
2066                         pcop = Safe_calloc(1, sizeof(pCodeOpReg));
2067                         PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2;   /* access PLUSW register */
2068                         PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx );
2069                         PCOR(pcop)->r->wasUsed = 1;
2070                         PCOR(pcop)->r->isFree = 0;
2071       
2072                         PCOR(pcop)->instance = offset;
2073                         pcop->type = PCOR(pcop)->r->pc_type;
2074                         return (pcop);
2075
2076                 case AOP_IMMD:
2077                         DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
2078                         return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
2079
2080                 case AOP_STA:
2081                         /* pCodeOp is already allocated from aopForSym */
2082                         DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset);
2083                         pcop = pic16_pCodeOpCopy(aop->aopu.stk.pop[offset]);
2084                         return (pcop);
2085       
2086                 case AOP_ACC:
2087                         {
2088                           int rIdx = IDX_WREG;          //aop->aopu.aop_reg[offset]->rIdx;
2089
2090                                 fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
2091
2092                                 DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
2093         
2094                                 pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2095                                 PCOR(pcop)->rIdx = rIdx;
2096                                 PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
2097                                 PCOR(pcop)->r->wasUsed=1;
2098                                 PCOR(pcop)->r->isFree=0;
2099
2100                                 PCOR(pcop)->instance = offset;
2101                                 pcop->type = PCOR(pcop)->r->pc_type;
2102 //                              DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
2103                                 return pcop;
2104
2105
2106 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
2107 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2108
2109 //      assert( 0 );
2110                         }
2111         
2112     case AOP_DIR:
2113       DEBUGpic16_emitcode(";","%d\tAOP_DIR (name = %s)", __LINE__, aop->aopu.aop_dir);
2114       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2115         
2116 #if 0
2117     case AOP_PAGED:
2118       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
2119       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset, NULL);
2120 #endif
2121
2122     case AOP_REG:
2123       {
2124         int rIdx;
2125
2126 //      debugf2("aop = %p\toffset = %d\n", aop, offset);
2127 //      assert (aop && aop->aopu.aop_reg[offset] != NULL);
2128         rIdx = aop->aopu.aop_reg[offset]->rIdx;
2129
2130         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
2131         
2132         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2133 //      pcop->type = PO_GPR_REGISTER;
2134         PCOR(pcop)->rIdx = rIdx;
2135         PCOR(pcop)->r = pic16_allocWithIdx( rIdx );     //pic16_regWithIdx(rIdx);       
2136         PCOR(pcop)->r->wasUsed=1;
2137         PCOR(pcop)->r->isFree=0;
2138
2139         PCOR(pcop)->instance = offset;
2140         pcop->type = PCOR(pcop)->r->pc_type;
2141         
2142         DEBUGpic16_emitcode(";*+*", "%d\tAOP_REG type = %s", __LINE__, dumpPicOptype(pcop->type));
2143 //      rs = aop->aopu.aop_reg[offset]->name;
2144 //      DEBUGpic16_emitcode(";","%d register idx = %d name = %s",__LINE__,rIdx,rs);
2145         return pcop;
2146       }
2147
2148     case AOP_CRY:
2149         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
2150
2151       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1, PO_GPR_REGISTER);
2152       PCOR(pcop)->instance = offset;
2153       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
2154       //if(PCOR(pcop)->r == NULL)
2155       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
2156       return pcop;
2157         
2158     case AOP_LIT:
2159         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
2160       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
2161
2162     case AOP_STR:
2163       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
2164       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
2165
2166       /*
2167       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2168       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
2169       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2170       pcop->type = PCOR(pcop)->r->pc_type;
2171       pcop->name = PCOR(pcop)->r->name;
2172
2173       return pcop;
2174       */
2175
2176     case AOP_PCODE:
2177       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
2178                           __LINE__, 
2179                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
2180       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
2181       switch( aop->aopu.pcop->type ) {
2182         case PO_DIR: PCOR(pcop)->instance += offset; break;
2183         case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
2184         case PO_WREG:
2185             assert (offset==0);
2186             break;
2187         default:
2188           fprintf (stderr, "%s: unhandled aop->aopu.pcop->type %d\n", __FUNCTION__, aop->aopu.pcop->type);
2189           assert( 0 );  /* should never reach here */;
2190       }
2191       return pcop;
2192     }
2193
2194     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2195            "pic16_popGet got unsupported aop->type");
2196     exit(0);
2197 }
2198 /*-----------------------------------------------------------------*/
2199 /* pic16_aopPut - puts a string for a aop                                */
2200 /*-----------------------------------------------------------------*/
2201 void pic16_aopPut (asmop *aop, char *s, int offset)
2202 {
2203     char *d = buffer ;
2204     symbol *lbl ;
2205
2206     return;
2207
2208     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2209
2210     if (aop->size && offset > ( aop->size - 1)) {
2211         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2212                "pic16_aopPut got offset > aop->size");
2213         exit(0);
2214     }
2215
2216     /* will assign value to value */
2217     /* depending on where it is ofcourse */
2218     switch (aop->type) {
2219     case AOP_DIR:
2220       if (offset) {
2221         sprintf(d,"(%s + %d)",
2222                 aop->aopu.aop_dir,offset);
2223         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
2224
2225       } else
2226             sprintf(d,"%s",aop->aopu.aop_dir);
2227         
2228         if (strcmp(d,s)) {
2229           DEBUGpic16_emitcode(";","%d",__LINE__);
2230           if(strcmp(s,"W"))
2231             pic16_emitcode("movf","%s,w",s);
2232           pic16_emitcode("movwf","%s",d);
2233
2234           if(strcmp(s,"W")) {
2235             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
2236             if(offset >= aop->size) {
2237               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2238               break;
2239             } else
2240               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
2241           }
2242
2243           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2244
2245
2246         }
2247         break;
2248         
2249     case AOP_REG:
2250       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
2251         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
2252           /*
2253             if (*s == '@'           ||
2254                 strcmp(s,"r0") == 0 ||
2255                 strcmp(s,"r1") == 0 ||
2256                 strcmp(s,"r2") == 0 ||
2257                 strcmp(s,"r3") == 0 ||
2258                 strcmp(s,"r4") == 0 ||
2259                 strcmp(s,"r5") == 0 ||
2260                 strcmp(s,"r6") == 0 || 
2261                 strcmp(s,"r7") == 0 )
2262                 pic16_emitcode("mov","%s,%s  ; %d",
2263                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
2264             else
2265           */
2266
2267           if(strcmp(s,"W")==0 )
2268             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
2269
2270           pic16_emitcode("movwf","%s",
2271                    aop->aopu.aop_reg[offset]->name);
2272
2273           if(strcmp(s,zero)==0) {
2274             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2275
2276           } else if(strcmp(s,"W")==0) {
2277             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2278             pcop->type = PO_GPR_REGISTER;
2279
2280             PCOR(pcop)->rIdx = -1;
2281             PCOR(pcop)->r = NULL;
2282
2283             DEBUGpic16_emitcode(";","%d",__LINE__);
2284             pcop->name = Safe_strdup(s);
2285             pic16_emitpcode(POC_MOVFW,pcop);
2286             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2287           } else if(strcmp(s,one)==0) {
2288             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
2289             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
2290           } else {
2291             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
2292           }
2293         }
2294         break;
2295         
2296     case AOP_DPTR:
2297     case AOP_DPTR2:
2298     
2299     if (aop->type == AOP_DPTR2)
2300     {
2301         genSetDPTR(1);
2302     }
2303     
2304         if (aop->code) {
2305             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2306                    "pic16_aopPut writting to code space");
2307             exit(0);
2308         }
2309         
2310         while (offset > aop->coff) {
2311             aop->coff++;
2312             pic16_emitcode ("inc","dptr");
2313         }
2314         
2315         while (offset < aop->coff) {
2316             aop->coff-- ;
2317             pic16_emitcode("lcall","__decdptr");
2318         }
2319         
2320         aop->coff = offset;
2321         
2322         /* if not in accumulater */
2323         MOVA(s);        
2324         
2325         pic16_emitcode ("movx","@dptr,a");
2326         
2327     if (aop->type == AOP_DPTR2)
2328     {
2329         genSetDPTR(0);
2330     }
2331         break;
2332         
2333     case AOP_R0:
2334     case AOP_R1:
2335         while (offset > aop->coff) {
2336             aop->coff++;
2337             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
2338         }
2339         while (offset < aop->coff) {
2340             aop->coff-- ;
2341             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
2342         }
2343         aop->coff = offset;
2344         
2345         if (aop->paged) {
2346             MOVA(s);           
2347             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
2348             
2349         } else
2350             if (*s == '@') {
2351                 MOVA(s);
2352                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
2353             } else
2354                 if (strcmp(s,"r0") == 0 ||
2355                     strcmp(s,"r1") == 0 ||
2356                     strcmp(s,"r2") == 0 ||
2357                     strcmp(s,"r3") == 0 ||
2358                     strcmp(s,"r4") == 0 ||
2359                     strcmp(s,"r5") == 0 ||
2360                     strcmp(s,"r6") == 0 || 
2361                     strcmp(s,"r7") == 0 ) {
2362                     char buffer[10];
2363                     sprintf(buffer,"a%s",s);
2364                     pic16_emitcode("mov","@%s,%s",
2365                              aop->aopu.aop_ptr->name,buffer);
2366                 } else
2367                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
2368         
2369         break;
2370         
2371     case AOP_STK:
2372         if (strcmp(s,"a") == 0)
2373             pic16_emitcode("push","acc");
2374         else
2375             pic16_emitcode("push","%s",s);
2376         
2377         break;
2378         
2379     case AOP_CRY:
2380         /* if bit variable */
2381         if (!aop->aopu.aop_dir) {
2382             pic16_emitcode("clr","a");
2383             pic16_emitcode("rlc","a");
2384         } else {
2385             if (s == zero) 
2386                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
2387             else
2388                 if (s == one)
2389                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
2390                 else
2391                     if (!strcmp(s,"c"))
2392                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2393                     else {
2394                         lbl = newiTempLabel(NULL);
2395                         
2396                         if (strcmp(s,"a")) {
2397                             MOVA(s);
2398                         }
2399                         pic16_emitcode("clr","c");
2400                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
2401                         pic16_emitcode("cpl","c");
2402                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
2403                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
2404                     }
2405         }
2406         break;
2407         
2408     case AOP_STR:
2409         aop->coff = offset;
2410         if (strcmp(aop->aopu.aop_str[offset],s))
2411             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
2412         break;
2413         
2414     case AOP_ACC:
2415         aop->coff = offset;
2416         if (!offset && (strcmp(s,"acc") == 0))
2417             break;
2418         
2419         if (strcmp(aop->aopu.aop_str[offset],s))
2420             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
2421         break;
2422
2423     default :
2424         fprintf(stderr, "%s:%d: unknown aop->type = 0x%x\n", __FILE__, __LINE__, aop->type);
2425 //      werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
2426 //             "pic16_aopPut got unsupported aop->type");
2427 //      exit(0);    
2428     }    
2429
2430 }
2431
2432 /*-----------------------------------------------------------------*/
2433 /* pic16_mov2w - generate either a MOVLW or MOVFW based operand type     */
2434 /*-----------------------------------------------------------------*/
2435 void pic16_mov2w (asmop *aop, int offset)
2436 {
2437   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
2438
2439   if(is_LitAOp(aop))
2440     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
2441   else
2442     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
2443 }
2444
2445 void pic16_mov2f(asmop *dst, asmop *src, int offset)
2446 {
2447   if(is_LitAOp(src)) {
2448     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2449     pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset));
2450   } else {
2451     if(pic16_sameRegsOfs(src, dst, offset))return;
2452     pic16_emitpcode(POC_MOVFF, pic16_popGet2p( pic16_popGet(src, offset),
2453                       pic16_popGet(dst, offset)));
2454   }
2455 }
2456
2457 static void pic16_movLit2f(pCodeOp *pc, int lit)
2458 {
2459   if (0 == (lit & 0x00ff))
2460   {
2461     pic16_emitpcode (POC_CLRF, pc);
2462   } else if (0xff == (lit & 0x00ff))
2463   {
2464     pic16_emitpcode (POC_SETF, pc);
2465   } else {
2466     pic16_emitpcode (POC_MOVLW, pic16_popGetLit (lit & 0x00ff));
2467     if (pc->type != PO_WREG) pic16_emitpcode (POC_MOVWF, pc);
2468   }
2469 }
2470
2471 static void mov2fp(pCodeOp *dst, asmop *src, int offset)
2472 {
2473   if(is_LitAOp(src)) {
2474     pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset));
2475     pic16_emitpcode(POC_MOVWF, dst);
2476   } else {
2477     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(src, offset), dst));
2478   }
2479 }
2480
2481 void pic16_testStackOverflow(void)
2482 {
2483 #define GSTACK_TEST_NAME        "_gstack_test"
2484
2485   pic16_emitpcode(POC_CALL, pic16_popGetWithString( GSTACK_TEST_NAME ));
2486   
2487   {
2488     symbol *sym;
2489
2490       sym = newSymbol( GSTACK_TEST_NAME , 0 );
2491       sprintf(sym->rname, "%s", /*port->fun_prefix,*/ GSTACK_TEST_NAME);
2492 //      strcpy(sym->rname, GSTACK_TEST_NAME);
2493       checkAddSym(&externs, sym);
2494   }
2495
2496 }
2497
2498 /* push pcop into stack */
2499 void pic16_pushpCodeOp(pCodeOp *pcop)
2500 {
2501 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2502   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
2503   if(pic16_options.gstack)
2504     pic16_testStackOverflow();
2505     
2506 }
2507
2508 /* pop pcop from stack */
2509 void pic16_poppCodeOp(pCodeOp *pcop)
2510 {
2511   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( pic16_stack_preinc ), pcop));
2512   if(pic16_options.gstack)
2513     pic16_testStackOverflow();
2514 }
2515
2516
2517 /*-----------------------------------------------------------------*/
2518 /* pushw - pushes wreg to stack                                    */
2519 /*-----------------------------------------------------------------*/
2520 void pushw(void)
2521 {
2522   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2523   pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2524   if(pic16_options.gstack)
2525     pic16_testStackOverflow();
2526 }
2527
2528                 
2529 /*-----------------------------------------------------------------*/
2530 /* pushaop - pushes aop to stack                                   */
2531 /*-----------------------------------------------------------------*/
2532 void pushaop(asmop *aop, int offset)
2533 {
2534   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2535
2536   if(_G.resDirect)return;
2537   
2538   if(is_LitAOp(aop)) {
2539     pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset));
2540     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
2541   } else {
2542     pic16_emitpcode(POC_MOVFF,
2543       pic16_popGet2p(pic16_popGet(aop, offset), pic16_popCopyReg( pic16_stack_postdec )));
2544   }
2545
2546   if(pic16_options.gstack)
2547     pic16_testStackOverflow();
2548 }
2549
2550 /*-----------------------------------------------------------------*/
2551 /* popaop - pops aop from stack                                    */
2552 /*-----------------------------------------------------------------*/
2553 void popaop(asmop *aop, int offset)
2554 {
2555   DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
2556   pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_stack_preinc, PCOR(pic16_popGet(aop, offset)), 0));
2557   if(pic16_options.gstack)
2558     pic16_testStackOverflow();
2559 }
2560
2561 void popaopidx(asmop *aop, int offset, int index)
2562 {
2563   int ofs=1;
2564
2565     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2566
2567     if(STACK_MODEL_LARGE)ofs++;
2568
2569     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
2570     pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pic16_frame_plusw, PCOR(pic16_popGet(aop, offset)), 0));
2571     if(pic16_options.gstack)
2572       pic16_testStackOverflow();
2573 }
2574
2575 #if !(USE_GENERIC_SIGNED_SHIFT)
2576 /*-----------------------------------------------------------------*/
2577 /* reAdjustPreg - points a register back to where it should        */
2578 /*-----------------------------------------------------------------*/
2579 static void reAdjustPreg (asmop *aop)
2580 {
2581     int size ;
2582
2583     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2584     aop->coff = 0;
2585     if ((size = aop->size) <= 1)
2586         return ;
2587     size-- ;
2588     switch (aop->type) {
2589         case AOP_R0 :
2590         case AOP_R1 :
2591             while (size--)
2592                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
2593             break;          
2594         case AOP_DPTR :
2595         case AOP_DPTR2:
2596             if (aop->type == AOP_DPTR2)
2597             {
2598                 genSetDPTR(1);
2599             } 
2600             while (size--)
2601             {
2602                 pic16_emitcode("lcall","__decdptr");
2603             }
2604                 
2605             if (aop->type == AOP_DPTR2)
2606             {
2607                 genSetDPTR(0);
2608             }                
2609             break;  
2610
2611     }   
2612
2613 }
2614 #endif
2615
2616 #if 0
2617 /*-----------------------------------------------------------------*/
2618 /* opIsGptr: returns non-zero if the passed operand is             */   
2619 /* a generic pointer type.                                         */
2620 /*-----------------------------------------------------------------*/ 
2621 static int opIsGptr(operand *op)
2622 {
2623     sym_link *type = operandType(op);
2624     
2625     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2626     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2627     {
2628         return 1;
2629     }
2630     return 0;        
2631 }
2632 #endif
2633
2634 /*-----------------------------------------------------------------*/
2635 /* pic16_getDataSize - get the operand data size                         */
2636 /*-----------------------------------------------------------------*/
2637 int pic16_getDataSize(operand *op)
2638 {
2639     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2640
2641
2642     return AOP_SIZE(op);
2643
2644     // tsd- in the pic port, the genptr size is 1, so this code here
2645     // fails. ( in the 8051 port, the size was 4).
2646 #if 0
2647     int size;
2648     size = AOP_SIZE(op);
2649     if (size == GPTRSIZE)
2650     {
2651         sym_link *type = operandType(op);
2652         if (IS_GENPTR(type))
2653         {
2654             /* generic pointer; arithmetic operations
2655              * should ignore the high byte (pointer type).
2656              */
2657             size--;
2658     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2659         }
2660     }
2661     return size;
2662 #endif
2663 }
2664
2665 /*-----------------------------------------------------------------*/
2666 /* pic16_outAcc - output Acc                                             */
2667 /*-----------------------------------------------------------------*/
2668 void pic16_outAcc(operand *result)
2669 {
2670   int size,offset;
2671   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2672   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2673
2674
2675   size = pic16_getDataSize(result);
2676   if(size){
2677     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2678     size--;
2679     offset = 1;
2680     /* unsigned or positive */
2681     while(size--)
2682       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2683   }
2684
2685 }
2686
2687 /*-----------------------------------------------------------------*/
2688 /* pic16_outBitC - output a bit C                                  */
2689 /*                 Move to result the value of Carry flag -- VR    */
2690 /*-----------------------------------------------------------------*/
2691 void pic16_outBitC(operand *result)
2692 {
2693   int i;
2694
2695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2696
2697     /* if the result is bit */
2698     if (AOP_TYPE(result) == AOP_CRY) {
2699         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2700         pic16_aopPut(AOP(result),"c",0);
2701     } else {
2702
2703         i = AOP_SIZE(result);
2704         while(i--) {
2705                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2706         }
2707         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2708     }
2709 }
2710
2711 /*-----------------------------------------------------------------*/
2712 /* pic16_outBitOp - output a bit from Op                           */
2713 /*                 Move to result the value of set/clr op -- VR    */
2714 /*-----------------------------------------------------------------*/
2715 void pic16_outBitOp(operand *result, pCodeOp *pcop)
2716 {
2717   int i;
2718
2719     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2720
2721     /* if the result is bit */
2722     if (AOP_TYPE(result) == AOP_CRY) {
2723         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2724         pic16_aopPut(AOP(result),"c",0);
2725     } else {
2726
2727         i = AOP_SIZE(result);
2728         while(i--) {
2729                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2730         }
2731         pic16_emitpcode(POC_RRCF, pcop);          
2732         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2733     }
2734 }
2735
2736 /*-----------------------------------------------------------------*/
2737 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2738 /*-----------------------------------------------------------------*/
2739 void pic16_toBoolean(operand *oper)
2740 {
2741     int size = AOP_SIZE(oper) - 1;
2742     int offset = 1;
2743
2744     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2745
2746     if ( AOP_TYPE(oper) != AOP_ACC) {
2747       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2748     }
2749     while (size--) {
2750       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2751     }
2752 }
2753
2754 /*-----------------------------------------------------------------*/
2755 /* genUminusFloat - unary minus for floating points                */
2756 /*-----------------------------------------------------------------*/
2757 static void genUminusFloat(operand *op,operand *result)
2758 {
2759   int size ,offset =0 ;
2760   
2761     FENTRY;
2762     /* for this we just need to flip the 
2763     first it then copy the rest in place */
2764     size = AOP_SIZE(op);
2765     assert( size == AOP_SIZE(result) );
2766
2767     while(size--) {
2768       pic16_mov2f(AOP(result), AOP(op), offset);
2769       offset++;
2770     }
2771     
2772     /* toggle the MSB's highest bit */
2773     pic16_emitpcode(POC_BTG, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), offset-1), 7));
2774 }
2775
2776 /*-----------------------------------------------------------------*/
2777 /* genUminus - unary minus code generation                         */
2778 /*-----------------------------------------------------------------*/
2779 static void genUminus (iCode *ic)
2780 {
2781   int size, i;
2782   sym_link *optype, *rtype;
2783   symbol *label;
2784   int needLabel=0;
2785
2786     FENTRY;     
2787     
2788     /* assign asmops */
2789     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2790     pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2791
2792     /* if both in bit space then special case */
2793     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2794       && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2795         
2796         pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2797         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2798         pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2799         goto release; 
2800     } 
2801
2802     optype = operandType(IC_LEFT(ic));
2803     rtype = operandType(IC_RESULT(ic));
2804
2805
2806     /* if float then do float stuff */
2807     if (IS_FLOAT(optype) || IS_FIXED(optype)) {
2808       if(IS_FIXED(optype))
2809         debugf("implement fixed16x16 type\n", 0);
2810         
2811         genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2812         goto release;
2813     }
2814
2815     /* otherwise subtract from zero by taking the 2's complement */
2816     size = AOP_SIZE(IC_LEFT(ic));
2817     assert( size == AOP_SIZE(IC_RESULT(ic)) );
2818     label = newiTempLabel ( NULL );
2819     
2820     if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2821       for (i=size-1; i > 0; i--) {
2822         pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2823       } // for
2824       pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0));
2825       for (i=1; i < size; i++) {
2826         if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; }
2827         pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i));
2828       } // for
2829     } else {
2830       for (i=size-1; i >= 0; i--) {
2831         pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i));
2832         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i));
2833       } // for
2834       if (size > 1) {
2835         for (i=0; i < size-2; i++) {
2836           pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i));
2837           pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++;
2838         } // for
2839         pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2));
2840       } // if
2841       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1));
2842     }
2843     if (needLabel)
2844       pic16_emitpLabel (label->key);
2845
2846 release:
2847     /* release the aops */
2848     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2849     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2850 }
2851
2852 #if 0
2853 /*-----------------------------------------------------------------*/
2854 /* saveRegisters - will look for a call and save the registers     */
2855 /*-----------------------------------------------------------------*/
2856 static void saveRegisters(iCode *lic) 
2857 {
2858     int i;
2859     iCode *ic;
2860     bitVect *rsave;
2861     sym_link *dtype;
2862
2863     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2864     /* look for call */
2865     for (ic = lic ; ic ; ic = ic->next) 
2866         if (ic->op == CALL || ic->op == PCALL)
2867             break;
2868
2869     if (!ic) {
2870         fprintf(stderr,"found parameter push with no function call\n");
2871         return ;
2872     }
2873
2874     /* if the registers have been saved already then
2875     do nothing */
2876     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2877         return ;
2878
2879     /* find the registers in use at this time 
2880     and push them away to safety */
2881     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2882                           ic->rUsed);
2883
2884     ic->regsSaved = 1;
2885     if (options.useXstack) {
2886         if (bitVectBitValue(rsave,R0_IDX))
2887             pic16_emitcode("mov","b,r0");
2888         pic16_emitcode("mov","r0,%s",spname);
2889         for (i = 0 ; i < pic16_nRegs ; i++) {
2890             if (bitVectBitValue(rsave,i)) {
2891                 if (i == R0_IDX)
2892                     pic16_emitcode("mov","a,b");
2893                 else
2894                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2895                 pic16_emitcode("movx","@r0,a");
2896                 pic16_emitcode("inc","r0");
2897             }
2898         }
2899         pic16_emitcode("mov","%s,r0",spname);
2900         if (bitVectBitValue(rsave,R0_IDX))
2901             pic16_emitcode("mov","r0,b");           
2902     }// else
2903     //for (i = 0 ; i < pic16_nRegs ; i++) {
2904     //    if (bitVectBitValue(rsave,i))
2905     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2906     //}
2907
2908     dtype = operandType(IC_LEFT(ic));
2909     if (currFunc && dtype && 
2910         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2911         IFFUNC_ISISR(currFunc->type) &&
2912         !ic->bankSaved) 
2913
2914         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2915
2916 }
2917 /*-----------------------------------------------------------------*/
2918 /* unsaveRegisters - pop the pushed registers                      */
2919 /*-----------------------------------------------------------------*/
2920 static void unsaveRegisters (iCode *ic)
2921 {
2922     int i;
2923     bitVect *rsave;
2924
2925     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2926     /* find the registers in use at this time 
2927     and push them away to safety */
2928     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2929                           ic->rUsed);
2930     
2931     if (options.useXstack) {
2932         pic16_emitcode("mov","r0,%s",spname);   
2933         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2934             if (bitVectBitValue(rsave,i)) {
2935                 pic16_emitcode("dec","r0");
2936                 pic16_emitcode("movx","a,@r0");
2937                 if (i == R0_IDX)
2938                     pic16_emitcode("mov","b,a");
2939                 else
2940                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2941             }       
2942
2943         }
2944         pic16_emitcode("mov","%s,r0",spname);
2945         if (bitVectBitValue(rsave,R0_IDX))
2946             pic16_emitcode("mov","r0,b");
2947     } //else
2948     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2949     //    if (bitVectBitValue(rsave,i))
2950     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2951     //}
2952
2953 }  
2954 #endif
2955
2956 #if 0  // patch 14
2957 /*-----------------------------------------------------------------*/
2958 /* pushSide -                                                      */
2959 /*-----------------------------------------------------------------*/
2960 static void pushSide(operand * oper, int size)
2961 {
2962         int offset = 0;
2963     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2964         while (size--) {
2965                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2966                 if (AOP_TYPE(oper) != AOP_REG &&
2967                     AOP_TYPE(oper) != AOP_DIR &&
2968                     strcmp(l,"a") ) {
2969                         pic16_emitcode("mov","a,%s",l);
2970                         pic16_emitcode("push","acc");
2971                 } else
2972                         pic16_emitcode("push","%s",l);
2973         }
2974 }
2975 #endif // patch 14
2976
2977 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2978 {
2979   if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) {
2980     pic16_emitpcode(POC_MOVFW, src);
2981     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2982   } else {
2983     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2984         src, pic16_popGet(AOP(op), offset)));
2985   }
2986 }
2987
2988
2989 /*-----------------------------------------------------------------*/
2990 /* assignResultValue - assign results to oper, rescall==1 is       */
2991 /*                     called from genCall() or genPcall()         */
2992 /*-----------------------------------------------------------------*/
2993 static void assignResultValue(operand * oper, int rescall)
2994 {
2995   int size = AOP_SIZE(oper);
2996   int offset=0;
2997   
2998     FENTRY2;
2999 //    DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
3000     DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
3001
3002     if(rescall) {
3003       /* assign result from a call/pcall function() */
3004                 
3005       /* function results are stored in a special order,
3006        * see top of file with Function return policy, or manual */
3007
3008       if(size <= 4) {
3009         /* 8-bits, result in WREG */
3010         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
3011                         
3012         if(size>1) {
3013           /* 16-bits, result in PRODL:WREG */
3014           pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
3015         }
3016                         
3017         if(size>2) {
3018           /* 24-bits, result in PRODH:PRODL:WREG */
3019           pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
3020         }
3021                         
3022         if(size>3) {
3023           /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
3024           pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
3025         }
3026       
3027       } else {
3028         /* >32-bits, result on stack, and FSR0 points to beginning.
3029          * Fix stack when done */
3030         /* FIXME FIXME */
3031 //      debugf("WARNING: Possible bug when returning more than 4-bytes\n");
3032         while (size--) {
3033 //          DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3034 //          DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3035                 
3036           popaopidx(AOP(oper), size, GpsuedoStkPtr);
3037           GpsuedoStkPtr++;
3038         }
3039                         
3040         /* fix stack */
3041         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
3042         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3043         if(STACK_MODEL_LARGE) {
3044           emitSKPNC;
3045           pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));     //&pic16_pc_fsr1h ));
3046         }
3047       }                 
3048     } else {
3049       int areg = 0;             /* matching argument register */
3050       
3051 //      debugf("_G.useWreg = %d\tGpsuedoStkPtr = %d\n", _G.useWreg, GpsuedoStkPtr);
3052       areg = SPEC_ARGREG( OP_SYM_ETYPE( oper ) ) - 1;
3053
3054
3055       /* its called from genReceive (probably) -- VR */
3056       /* I hope this code will not be called from somewhere else in the future! 
3057        * We manually set the pseudo stack pointer in genReceive. - dw
3058        */
3059       if(!GpsuedoStkPtr && _G.useWreg) {
3060 //        DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
3061
3062         /* The last byte in the assignment is in W */
3063         if(areg <= GpsuedoStkPtr) {
3064           size--;
3065           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), offset /*size*/));
3066           offset++;
3067 //          debugf("receive from WREG\n", 0);
3068         }
3069         GpsuedoStkPtr++; /* otherwise the calculation below fails (-_G.useWreg) */
3070       }
3071 //      GpsuedoStkPtr++;
3072       _G.stack_lat = AOP_SIZE(oper)-1;
3073
3074       while (size) {
3075         size--;
3076         GpsuedoStkPtr++;
3077         popaopidx(AOP(oper), offset, GpsuedoStkPtr - _G.useWreg);
3078 //        debugf("receive from STACK\n", 0);
3079         offset++;
3080       }
3081     }
3082 }
3083
3084
3085 /*-----------------------------------------------------------------*/
3086 /* genIpush - generate code for pushing this gets a little complex */
3087 /*-----------------------------------------------------------------*/
3088 static void genIpush (iCode *ic)
3089 {
3090 //  int size, offset=0;
3091
3092   FENTRY;
3093   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3094
3095   if(ic->parmPush) {
3096     pic16_aopOp(IC_LEFT(ic), ic, FALSE );
3097
3098     /* send to stack as normal */
3099     addSet(&_G.sendSet,ic);
3100 //    addSetHead(&_G.sendSet,ic);
3101     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3102   }
3103
3104         
3105 #if 0
3106     int size, offset = 0 ;
3107     char *l;
3108
3109
3110     /* if this is not a parm push : ie. it is spill push 
3111     and spill push is always done on the local stack */
3112     if (!ic->parmPush) {
3113
3114         /* and the item is spilt then do nothing */
3115         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3116             return ;
3117
3118         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3119         size = AOP_SIZE(IC_LEFT(ic));
3120         /* push it on the stack */
3121         while(size--) {
3122             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
3123             if (*l == '#') {
3124                 MOVA(l);
3125                 l = "acc";
3126             }
3127             pic16_emitcode("push","%s",l);
3128         }
3129         return ;        
3130     }
3131
3132     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3133 #endif
3134 }
3135
3136 /*-----------------------------------------------------------------*/
3137 /* genIpop - recover the registers: can happen only for spilling   */
3138 /*-----------------------------------------------------------------*/
3139 static void genIpop (iCode *ic)
3140 {
3141   FENTRY;
3142   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3143 #if 0
3144     int size,offset ;
3145
3146
3147     /* if the temp was not pushed then */
3148     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
3149         return ;
3150
3151     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3152     size = AOP_SIZE(IC_LEFT(ic));
3153     offset = (size-1);
3154     while (size--) 
3155         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
3156                                    FALSE,TRUE));
3157
3158     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
3159 #endif
3160 }
3161
3162 #if 0
3163 /*-----------------------------------------------------------------*/
3164 /* unsaverbank - restores the resgister bank from stack            */
3165 /*-----------------------------------------------------------------*/
3166 static void unsaverbank (int bank,iCode *ic,bool popPsw)
3167 {
3168   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3169 #if 0
3170     int i;
3171     asmop *aop ;
3172     regs *r = NULL;
3173
3174     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3175     if (popPsw) {
3176         if (options.useXstack) {
3177             aop = newAsmop(0);
3178             r = getFreePtr(ic,&aop,FALSE);
3179             
3180             
3181             pic16_emitcode("mov","%s,_spx",r->name);
3182             pic16_emitcode("movx","a,@%s",r->name);
3183             pic16_emitcode("mov","psw,a");
3184             pic16_emitcode("dec","%s",r->name);
3185             
3186         }else
3187             pic16_emitcode ("pop","psw");
3188     }
3189
3190     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
3191         if (options.useXstack) {       
3192             pic16_emitcode("movx","a,@%s",r->name);
3193             //pic16_emitcode("mov","(%s+%d),a",
3194             //       regspic16[i].base,8*bank+regspic16[i].offset);
3195             pic16_emitcode("dec","%s",r->name);
3196
3197         } else 
3198           pic16_emitcode("pop",""); //"(%s+%d)",
3199         //regspic16[i].base,8*bank); //+regspic16[i].offset);
3200     }
3201
3202     if (options.useXstack) {
3203
3204         pic16_emitcode("mov","_spx,%s",r->name);
3205         pic16_freeAsmop(NULL,aop,ic,TRUE);
3206
3207     }
3208 #endif 
3209 }
3210
3211 /*-----------------------------------------------------------------*/
3212 /* saverbank - saves an entire register bank on the stack          */
3213 /*-----------------------------------------------------------------*/
3214 static void saverbank (int bank, iCode *ic, bool pushPsw)
3215 {
3216   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3217 #if 0
3218     int i;
3219     asmop *aop ;
3220     regs *r = NULL;
3221
3222     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3223     if (options.useXstack) {
3224
3225         aop = newAsmop(0);
3226         r = getFreePtr(ic,&aop,FALSE);  
3227         pic16_emitcode("mov","%s,_spx",r->name);
3228
3229     }
3230
3231     for (i = 0 ; i < pic16_nRegs ;i++) {
3232         if (options.useXstack) {
3233             pic16_emitcode("inc","%s",r->name);
3234             //pic16_emitcode("mov","a,(%s+%d)",
3235             //         regspic16[i].base,8*bank+regspic16[i].offset);
3236             pic16_emitcode("movx","@%s,a",r->name);           
3237         } else 
3238           pic16_emitcode("push","");// "(%s+%d)",
3239                      //regspic16[i].base,8*bank+regspic16[i].offset);
3240     }
3241     
3242     if (pushPsw) {
3243         if (options.useXstack) {
3244             pic16_emitcode("mov","a,psw");
3245             pic16_emitcode("movx","@%s,a",r->name);     
3246             pic16_emitcode("inc","%s",r->name);
3247             pic16_emitcode("mov","_spx,%s",r->name);       
3248             pic16_freeAsmop (NULL,aop,ic,TRUE);
3249             
3250         } else
3251             pic16_emitcode("push","psw");
3252         
3253         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
3254     }
3255     ic->bankSaved = 1;
3256 #endif
3257 }
3258 #endif  /* 0 */
3259
3260
3261 static int wparamCmp(void *p1, void *p2)
3262 {
3263   return (!strcmp((char *)p1, (char *)p2));
3264 }
3265
3266 int inWparamList(char *s)
3267 {
3268   return isinSetWith(wparamList, s, wparamCmp);
3269
3270
3271
3272 /*-----------------------------------------------------------------*/
3273 /* genCall - generates a call statement                            */
3274 /*-----------------------------------------------------------------*/
3275 static void genCall (iCode *ic)
3276 {
3277   sym_link *ftype;   
3278   int stackParms=0;
3279   int use_wreg=0;
3280   int inwparam=0;
3281   char *fname;
3282   
3283     FENTRY;
3284
3285     ftype = OP_SYM_TYPE(IC_LEFT(ic));
3286     /* if caller saves & we have not saved then */
3287 //    if (!ic->regsSaved)
3288 //      saveRegisters(ic);
3289
3290         /* initialise stackParms for IPUSH pushes */
3291 //      stackParms = psuedoStkPtr;
3292 //      fprintf(stderr, "%s:%d ic parmBytes = %d\n", __FILE__, __LINE__, ic->parmBytes);
3293     fname = OP_SYMBOL(IC_LEFT(ic))->rname[0]?OP_SYMBOL(IC_LEFT(ic))->rname:OP_SYMBOL(IC_LEFT(ic))->name;
3294     inwparam = (inWparamList(OP_SYMBOL(IC_LEFT(ic))->name)) || (FUNC_ISWPARAM(OP_SYM_TYPE(IC_LEFT(ic))));
3295
3296 #if 0
3297     gpsimDebug_StackDump(__FILE__, __LINE__, fname );
3298 #endif
3299
3300     /* if send set is not empty the assign */
3301     if (_G.sendSet) {
3302       iCode *sic;
3303       int psuedoStkPtr=-1; 
3304       int firstTimeThruLoop = 1;
3305
3306
3307         /* reverse sendSet if function is not reentrant */
3308         if(!IFFUNC_ISREENT(ftype))
3309           _G.sendSet = reverseSet(_G.sendSet);
3310
3311         /* First figure how many parameters are getting passed */
3312         stackParms = 0;
3313         use_wreg = 0;
3314         
3315         for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3316           int size;
3317 //          int offset = 0;
3318
3319             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3320             size = AOP_SIZE(IC_LEFT(sic));
3321
3322             stackParms += size;
3323
3324             /* pass the last byte through WREG */
3325             if(inwparam) {
3326
3327               while (size--) {
3328                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3329                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3330                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3331
3332                 if(!firstTimeThruLoop) {
3333                   /* If this is not the first time we've been through the loop
3334                    * then we need to save the parameter in a temporary
3335                    * register. The last byte of the last parameter is
3336                    * passed in W. */
3337
3338                   pushw();
3339 //                  --psuedoStkPtr;             // sanity check
3340                   use_wreg = 1;
3341                 }
3342                 
3343                 firstTimeThruLoop=0;
3344
3345                 pic16_mov2w (AOP(IC_LEFT(sic)), size);
3346
3347 //                offset++;
3348               }
3349             } else {
3350               /* all arguments are passed via stack */
3351               use_wreg = 0;
3352
3353               while (size--) {
3354                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3355                       pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3356                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3357
3358 //                pushaop(AOP(IC_LEFT(sic)), size);
3359                                 pic16_mov2w( AOP(IC_LEFT(sic)), size );
3360                                 
3361                 if(!_G.resDirect)
3362                   pushw();
3363               }
3364             }
3365
3366             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3367           }
3368
3369           if(inwparam) {
3370             if(IFFUNC_HASVARARGS(ftype) || IFFUNC_ISREENT(ftype)) {
3371               pushw();  /* save last parameter to stack if functions has varargs */
3372               use_wreg = 0;
3373             } else
3374               use_wreg = 1;
3375           } else use_wreg = 0;
3376
3377           _G.stackRegSet = _G.sendSet;
3378           _G.sendSet = NULL;
3379     }
3380
3381     /* make the call */
3382     pic16_emitpcode(POC_CALL,pic16_popGetWithString(fname));
3383
3384     GpsuedoStkPtr=0;
3385     
3386     /* if we need to assign a result value */
3387     if ((IS_ITEMP(IC_RESULT(ic))
3388           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3389               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3390         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3391
3392       _G.accInUse++;
3393       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3394       _G.accInUse--;
3395
3396       assignResultValue(IC_RESULT(ic), 1);
3397
3398       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3399                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3400                 
3401       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3402     }
3403
3404     if(!stackParms && ic->parmBytes) {
3405       stackParms = ic->parmBytes;
3406     }
3407       
3408     stackParms -= use_wreg;
3409     
3410     if(stackParms>0) {
3411       if(stackParms == 1) {
3412         pic16_emitpcode(POC_INCF, pic16_popCopyReg(pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3413       } else {
3414         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3415         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));      //&pic16_pc_fsr1l ));
3416       }
3417       if(STACK_MODEL_LARGE) {
3418         emitSKPNC;
3419         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));       //&pic16_pc_fsr1h ));
3420       }
3421     }
3422
3423 #if 0
3424     gpsimDebug_StackDump(__FILE__, __LINE__, fname);
3425 #endif
3426
3427     /* adjust the stack for parameters if required */
3428 //    fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3429
3430 #if 0
3431       /* if register bank was saved then pop them */
3432       if (ic->bankSaved)
3433         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3434
3435       /* if we hade saved some registers then unsave them */
3436       if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3437         unsaveRegisters (ic);
3438 #endif
3439 }
3440
3441
3442
3443 /*-----------------------------------------------------------------*/
3444 /* genPcall - generates a call by pointer statement                */
3445 /*            new version, created from genCall - HJD              */
3446 /*-----------------------------------------------------------------*/
3447 static void genPcall (iCode *ic)
3448 {
3449   sym_link *fntype;
3450   int stackParms=0;
3451   symbol *retlbl = newiTempLabel(NULL);
3452   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
3453   
3454     FENTRY;
3455
3456     fntype = operandType( IC_LEFT(ic) )->next;
3457
3458     /* if send set is not empty the assign */
3459     if (_G.sendSet) {
3460       iCode *sic;
3461       int psuedoStkPtr=-1; 
3462
3463       /* reverse sendSet if function is not reentrant */
3464       if(!IFFUNC_ISREENT(fntype))
3465         _G.sendSet = reverseSet(_G.sendSet);
3466
3467       stackParms = 0;
3468       
3469       for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
3470         int size;
3471
3472           pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3473           size = AOP_SIZE(IC_LEFT(sic));
3474           stackParms += size;
3475
3476           /* all parameters are passed via stack, since WREG is clobbered
3477            * by the calling sequence */
3478           while (size--) {
3479             DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3480             pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
3481             DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
3482
3483             pic16_mov2w (AOP(IC_LEFT(sic)), size);
3484             pushw();
3485           }
3486
3487           pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3488       }
3489
3490       _G.stackRegSet = _G.sendSet;
3491       _G.sendSet = NULL;
3492     }
3493
3494     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3495
3496     // push return address
3497     // push $ on return stack, then replace with retlbl
3498
3499     /* Thanks to Thorsten Klose for pointing out that the following
3500      * snippet should be interrupt safe */
3501     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_intcon), pic16_popCopyReg(&pic16_pc_postdec1)));
3502     pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_intcon), 7));
3503
3504     pic16_emitpcodeNULLop(POC_PUSH);
3505
3506     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
3507     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
3508     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
3509     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
3510     pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
3511     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
3512
3513
3514     /* restore interrupt control register */
3515     pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_preinc1));
3516     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_intcon));
3517
3518     /* make the call by writing the pointer into pc */
3519     mov2fp(pic16_popCopyReg(&pic16_pc_pclatu), AOP(IC_LEFT(ic)), 2);
3520     mov2fp(pic16_popCopyReg(&pic16_pc_pclath), AOP(IC_LEFT(ic)), 1);
3521
3522     // note: MOVFF to PCL not allowed
3523     pic16_mov2w(AOP(IC_LEFT(ic)), 0);
3524     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
3525
3526
3527     /* return address is here: (X) */
3528     pic16_emitpLabelFORCE(retlbl->key);
3529
3530     pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3531
3532     GpsuedoStkPtr=0;
3533     /* if we need assign a result value */
3534     if ((IS_ITEMP(IC_RESULT(ic))
3535           && (OP_SYMBOL(IC_RESULT(ic))->nRegs
3536               || OP_SYMBOL(IC_RESULT(ic))->spildir ))
3537         || IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3538
3539       _G.accInUse++;
3540       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3541       _G.accInUse--;
3542
3543       assignResultValue(IC_RESULT(ic), 1);
3544
3545       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3546               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3547                 
3548       pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3549     }
3550
3551 //    stackParms -= use_wreg;
3552     
3553     if(stackParms>0) {
3554       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3555       pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3556       if(STACK_MODEL_LARGE) {
3557         emitSKPNC;
3558         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3559       }
3560     }
3561 }
3562
3563 /*-----------------------------------------------------------------*/
3564 /* resultRemat - result  is rematerializable                       */
3565 /*-----------------------------------------------------------------*/
3566 static int resultRemat (iCode *ic)
3567 {
3568   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3569   if (SKIP_IC(ic) || ic->op == IFX)
3570     return 0;
3571
3572   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3573     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3574     if (sym->remat && !POINTER_SET(ic)) 
3575       return 1;
3576   }
3577
3578   return 0;
3579 }
3580
3581 #if defined(__BORLANDC__) || defined(_MSC_VER)
3582 #define STRCASECMP stricmp
3583 #else
3584 #define STRCASECMP strcasecmp
3585 #endif
3586
3587 #if 0
3588 /*-----------------------------------------------------------------*/
3589 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3590 /*-----------------------------------------------------------------*/
3591 static bool inExcludeList(char *s)
3592 {
3593   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3594     int i =0;
3595     
3596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3597     if (options.excludeRegs[i] &&
3598     STRCASECMP(options.excludeRegs[i],"none") == 0)
3599         return FALSE ;
3600
3601     for ( i = 0 ; options.excludeRegs[i]; i++) {
3602         if (options.excludeRegs[i] &&
3603         STRCASECMP(s,options.excludeRegs[i]) == 0)
3604             return TRUE;
3605     }
3606     return FALSE ;
3607 }
3608 #endif
3609
3610 /*-----------------------------------------------------------------*/
3611 /* genFunction - generated code for function entry                 */
3612 /*-----------------------------------------------------------------*/
3613 static void genFunction (iCode *ic)
3614 {
3615   symbol *sym;
3616   sym_link *ftype;
3617   
3618     FENTRY;
3619     DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,pic16_labelOffset,max_key);
3620
3621     pic16_labelOffset += (max_key+4);
3622     max_key=0;
3623     GpsuedoStkPtr=0;
3624     _G.nRegsSaved = 0;
3625         
3626     ftype = operandType(IC_LEFT(ic));
3627     sym = OP_SYMBOL(IC_LEFT(ic));
3628
3629     if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3630       /* create an absolute section at the interrupt vector:
3631        * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3632       symbol *asym;
3633       char asymname[128];
3634       pBlock *apb;
3635
3636 //        debugf("interrupt number: %hhi\n", FUNC_INTNO(sym->type));
3637
3638         if(FUNC_INTNO(sym->type) == INTNO_UNSPEC)
3639           sprintf(asymname, "ivec_%s", sym->name);
3640         else
3641           sprintf(asymname, "ivec_0x%x_%s", FUNC_INTNO(sym->type), sym->name);
3642   
3643         /* when an interrupt is declared as naked, do not emit the special
3644          * wrapper segment at vector address. The user should take care for
3645          * this instead. -- VR */
3646
3647         if(!IFFUNC_ISNAKED(ftype) && (FUNC_INTNO(sym->type) != INTNO_UNSPEC)) {
3648           asym = newSymbol(asymname, 0);
3649           apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3650           pic16_addpBlock( apb );
3651
3652           pic16_addpCode2pBlock(apb, pic16_newpCodeCharP(";-----------------------------------------"));
3653           pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3654           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3655           //pic16_addpCode2pBlock(apb, pic16_newpCode(POC_GOTO, pic16_newpCodeOpLabel (sym->rname, 0)));
3656           pic16_addpCode2pBlock(apb, pic16_newpCodeAsmDir ("GOTO", "%s", sym->rname)); /* this suppresses a warning in LinkFlow */
3657                 
3658           /* mark the end of this tiny function */
3659           pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3660         } else {
3661           sprintf(asymname, "%s", sym->rname);
3662         }
3663
3664         {
3665           absSym *abSym;
3666
3667             abSym = Safe_calloc(1, sizeof(absSym));
3668             strcpy(abSym->name, asymname);
3669
3670             switch( FUNC_INTNO(sym->type) ) {
3671               case 0: abSym->address = 0x000000; break;
3672               case 1: abSym->address = 0x000008; break;
3673               case 2: abSym->address = 0x000018; break;
3674               
3675               default:
3676 //                fprintf(stderr, "no interrupt number is given\n");
3677                 abSym->address = -1; break;
3678             }
3679
3680             /* relocate interrupt vectors if needed */
3681             if(abSym->address != -1)
3682               abSym->address += pic16_options.ivt_loc;
3683
3684             addSet(&absSymSet, abSym);
3685         }
3686     }
3687
3688     /* create the function header */
3689     pic16_emitcode(";","-----------------------------------------");
3690     pic16_emitcode(";"," function %s",sym->name);
3691     pic16_emitcode(";","-----------------------------------------");
3692
3693     pic16_emitcode("","%s:",sym->rname);
3694     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3695
3696     {
3697       absSym *ab;
3698
3699         for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet)) {
3700           if(!strcmp(ab->name, sym->rname)) {
3701             pic16_pBlockConvert2Absolute(pb);
3702             break;
3703           }
3704         }
3705     }
3706
3707     if(IFFUNC_ISNAKED(ftype)) {
3708       DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3709       return;
3710     }
3711         
3712     /* if critical function then turn interrupts off */
3713     if (IFFUNC_ISCRITICAL(ftype)) {
3714       //pic16_emitcode("clr","ea");
3715     }
3716
3717     currFunc = sym;             /* update the currFunc symbol */
3718     _G.fregsUsed = sym->regsUsed;
3719     _G.sregsAlloc = newBitVect(128);
3720     
3721
3722     /* if this is an interrupt service routine then
3723      * save wreg, status, bsr, prodl, prodh, fsr0l, fsr0h */
3724     if (IFFUNC_ISISR(sym->type)) {
3725         _G.usefastretfie = 1;   /* use shadow registers by default */
3726         
3727         /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3728         if(!FUNC_ISSHADOWREGS(sym->type)) {
3729           /* do not save WREG,STATUS,BSR for high priority interrupts
3730            * because they are stored in the hardware shadow registers already */
3731           _G.usefastretfie = 0;
3732           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3733           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3734           pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3735         }
3736
3737         /* these should really be optimized somehow, because not all
3738          * interrupt handlers modify them */
3739         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3740         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3741         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3742         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3743         
3744 //        pic16_pBlockConvert2ISR(pb);
3745     }
3746
3747     /* emit code to setup stack frame if user enabled,
3748      * and function is not main() */
3749     
3750 //    debugf(stderr, "function name: %s ARGS=%p\n", sym->name, FUNC_ARGS(sym->type));
3751     if(strcmp(sym->name, "main")) {
3752       if(0 
3753         || !options.ommitFramePtr 
3754 //        || sym->regsUsed
3755         || IFFUNC_ARGS(sym->type)
3756         || FUNC_HASSTACKPARM(sym->etype)
3757         ) {
3758         /* setup the stack frame */
3759         if(STACK_MODEL_LARGE)
3760           pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_hi));
3761         pic16_pushpCodeOp(pic16_popCopyReg(pic16_framepnt_lo));
3762
3763         if(STACK_MODEL_LARGE)
3764           pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_hi, pic16_framepnt_hi, 0));
3765         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( pic16_stackpnt_lo, pic16_framepnt_lo, 0));
3766       }
3767     }
3768
3769     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3770           && sym->stack) {
3771
3772       if (sym->stack > 127)werror(W_STACK_OVERFLOW, sym->name);
3773
3774       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack));
3775       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg( pic16_stackpnt_lo ));        //&pic16_pc_fsr1l));
3776       emitSKPC;
3777       pic16_emitpcode(POC_DECF, pic16_popCopyReg( pic16_stackpnt_hi ));         //&pic16_pc_fsr1h));
3778     }
3779           
3780     if(inWparamList(sym->name) || FUNC_ISWPARAM(sym->type)) {
3781       if(IFFUNC_HASVARARGS(sym->type) || IFFUNC_ISREENT(sym->type))
3782         _G.useWreg = 0;
3783       else
3784         _G.useWreg = 1;
3785     } else
3786       _G.useWreg = 0;
3787
3788     /* if callee-save to be used for this function
3789      * then save the registers being used in this function */
3790 //    if (IFFUNC_CALLEESAVES(sym->type))
3791     if(strcmp(sym->name, "main")) {
3792       int i;
3793
3794         /* if any registers used */
3795         if (sym->regsUsed) {
3796                   pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
3797
3798           if(!xinst) {
3799             /* save the registers used */
3800             DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3801             for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3802               if (bitVectBitValue(sym->regsUsed,i)) {
3803 #if 0
3804                 fprintf(stderr, "%s:%d local register w/rIdx = %d is used in function\n", __FUNCTION__, __LINE__, i);
3805 #endif
3806                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3807                 _G.nRegsSaved++;
3808
3809                 if(!pic16_regWithIdx(i)->wasUsed) {
3810                   fprintf(stderr, "%s:%d register %s is used in function but was wasUsed = 0\n",
3811                                 __FILE__, __LINE__, pic16_regWithIdx(i)->name);
3812                   pic16_regWithIdx(i)->wasUsed = 1;
3813                 }
3814               }
3815             }
3816           } else {
3817             
3818             /* xinst */
3819             DEBUGpic16_emitcode("; **", "Allocate a space in stack to be used as temporary registers");
3820             for(i=0;i<sym->regsUsed->size;i++) {
3821               if(bitVectBitValue(sym->regsUsed, i)) {
3822                 _G.nRegsSaved++;
3823               }
3824             }
3825                         
3826 //            pic16_emitpcode(POC_ADDFSR, pic16_popGetLit2(2, pic16_popGetLit(_G.nRegsSaved)));
3827           }
3828
3829           pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_END));
3830
3831         }
3832     }
3833         
3834     DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3835 //    fprintf(stderr, "Function '%s' uses %d bytes of stack\n", sym->name, sym->stack);
3836 }
3837
3838 /*-----------------------------------------------------------------*/
3839 /* genEndFunction - generates epilogue for functions               */
3840 /*-----------------------------------------------------------------*/
3841 static void genEndFunction (iCode *ic)
3842 {
3843   symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3844
3845     FENTRY;
3846
3847     if(IFFUNC_ISNAKED(sym->type)) {
3848       DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3849       return;
3850     }
3851
3852     _G.stack_lat = 0;
3853
3854     /* add code for ISCRITICAL */
3855     if(IFFUNC_ISCRITICAL(sym->type)) {
3856       /* if critical function, turn on interrupts */
3857       
3858       /* TODO: add code here -- VR */
3859     }
3860     
3861 //    sym->regsUsed = _G.fregsUsed;
3862     
3863     /* now we need to restore the registers */
3864     /* if any registers used */
3865
3866     /* first restore registers that might be used for stack access */
3867     if(_G.sregsAllocSet) {
3868     regs *sr;
3869     
3870       _G.sregsAllocSet = reverseSet( _G.sregsAllocSet );
3871       for(sr=setFirstItem(_G.sregsAllocSet) ; sr; sr=setNextItem(_G.sregsAllocSet)) {
3872         pic16_poppCodeOp( pic16_popRegFromIdx( sr->rIdx ) );
3873       }
3874     }
3875
3876     if (strcmp(sym->name, "main") && sym->regsUsed) {
3877       int i;
3878
3879         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_BEGIN));
3880         /* restore registers used */
3881         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3882         for ( i = sym->regsUsed->size; i >= 0; i--) {
3883           if (bitVectBitValue(sym->regsUsed,i)) {
3884             pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3885             _G.nRegsSaved--;
3886           }
3887         }
3888         pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_EXIT_END));
3889     }
3890
3891       
3892
3893     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)
3894           && sym->stack) {
3895       if (sym->stack == 1) {
3896         pic16_emitpcode(POC_INFSNZ, pic16_popCopyReg( pic16_stackpnt_lo ));
3897         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3898       } else {
3899         // we have to add more than one...
3900         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postinc ));    // this holds a return value!
3901         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(sym->stack-1));
3902         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( pic16_stackpnt_lo ));
3903         emitSKPNC;
3904         pic16_emitpcode(POC_INCF, pic16_popCopyReg( pic16_stackpnt_hi ));
3905         pic16_emitpcode(POC_COMF,  pic16_popCopyReg(&pic16_pc_wreg)); // WREG = -(WREG+1)!
3906         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_plusw)); // this holds a retrun value!
3907       }
3908     }
3909
3910     if(strcmp(sym->name, "main")) {
3911       if(0
3912         || !options.ommitFramePtr
3913 //        || sym->regsUsed
3914         || IFFUNC_ARGS(sym->type)
3915         || FUNC_HASSTACKPARM(sym->etype)
3916         ) {
3917         /* restore stack frame */
3918         pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_lo ));
3919         if(STACK_MODEL_LARGE)
3920           pic16_poppCodeOp( pic16_popCopyReg( pic16_framepnt_hi ));
3921       }
3922     }
3923
3924     _G.useWreg = 0;
3925
3926     if (IFFUNC_ISISR(sym->type)) {
3927       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3928       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3929       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3930       pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3931
3932       if(!FUNC_ISSHADOWREGS(sym->type)) {
3933         /* do not restore interrupt vector for WREG,STATUS,BSR
3934          * for high priority interrupt, see genFunction */
3935         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3936         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3937         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3938       }
3939 //      _G.interruptvector = 0;         /* sanity check */
3940
3941
3942       /* if debug then send end of function */
3943 /*      if (options.debug && currFunc)  */
3944       if (currFunc) {
3945         debugFile->writeEndFunction (currFunc, ic, 1);
3946       }
3947         
3948       if(_G.usefastretfie)
3949         pic16_emitpcode(POC_RETFIE, pic16_newpCodeOpLit(1));
3950       else
3951         pic16_emitpcodeNULLop(POC_RETFIE);
3952
3953       pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3954       
3955       _G.usefastretfie = 0;
3956       return;
3957     }
3958
3959     if (IFFUNC_ISCRITICAL(sym->type)) {
3960       pic16_emitcode("setb","ea");
3961     }
3962
3963     /* if debug then send end of function */
3964     if (currFunc) {
3965       debugFile->writeEndFunction (currFunc, ic, 1);
3966     }
3967
3968     /* insert code to restore stack frame, if user enabled it
3969      * and function is not main() */
3970          
3971
3972     pic16_emitpcodeNULLop(POC_RETURN);
3973
3974     /* Mark the end of a function */
3975     pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3976 }
3977
3978
3979 void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest)
3980 {
3981   unsigned long lit=1;
3982   operand *op;
3983
3984     op = IC_LEFT(ic);
3985   
3986     // this fails for is_LitOp(op) (if op is an AOP_PCODE)
3987     if(AOP_TYPE(op) == AOP_LIT) {
3988       if(!IS_FLOAT(operandType( op ))) {
3989         lit = (unsigned long)floatFromVal(AOP(op)->aopu.aop_lit);
3990       } else {
3991         union {
3992           unsigned long lit_int;
3993           float lit_float;
3994         } info;
3995         
3996         /* take care if literal is a float */
3997         info.lit_float = floatFromVal(AOP(op)->aopu.aop_lit);
3998         lit = info.lit_int;
3999       }
4000     }
4001
4002     if (AOP_TYPE(op) == AOP_LIT) {
4003       /* FIXME: broken for
4004        *   char __at(0x456) foo;
4005        *   return &foo;
4006        * (upper byte is 0x00 (__code space) instead of 0x80 (__data) */
4007       pic16_movLit2f(dest, (lit >> (8ul*offset)));
4008     } else if (AOP_TYPE(op) == AOP_PCODE
4009                 && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
4010       /* char *s= "aaa"; return s; */
4011       /* XXX: Using UPPER(__str_0) will yield 0b00XXXXXX, so
4012        *      that the generic pointer is interpreted correctly
4013        *      as referring to __code space, but this is fragile! */
4014       pic16_emitpcode(POC_MOVLW, pic16_popGet( AOP(op), offset ));
4015       /* XXX: should check that dest != WREG */
4016       pic16_emitpcode(POC_MOVWF, dest);
4017     } else {
4018       if(dest->type == PO_WREG && (offset == 0)) {
4019         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op), offset));
4020         return;
4021       }
4022       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op), offset), dest));
4023     }
4024 }
4025
4026 /*-----------------------------------------------------------------*/
4027 /* genRet - generate code for return statement                     */
4028 /*-----------------------------------------------------------------*/
4029 static void genRet (iCode *ic)
4030 {
4031   int size;
4032   operand *left;
4033
4034     FENTRY;
4035         /* if we have no return value then
4036          * just generate the "ret" */
4037         
4038         if (!IC_LEFT(ic)) 
4039                 goto jumpret;       
4040     
4041         /* we have something to return then
4042          * move the return value into place */
4043         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4044         size = AOP_SIZE(IC_LEFT(ic));
4045
4046         if(size <= 4) {
4047           if(size>3)
4048             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 3, pic16_popCopyReg(&pic16_pc_fsr0l));
4049           
4050           if(size>2)
4051             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 2, pic16_popCopyReg(&pic16_pc_prodh));
4052
4053           if(size>1)
4054             pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 1, pic16_popCopyReg(&pic16_pc_prodl));
4055           
4056           pic16_storeForReturn(ic, /*IC_LEFT(ic),*/ 0, pic16_popCopyReg(&pic16_pc_wreg));
4057
4058         } else {
4059                 /* >32-bits, setup stack and FSR0 */
4060                 while (size--) {
4061 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
4062 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
4063
4064                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
4065
4066 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
4067                         GpsuedoStkPtr++;
4068                 }
4069                         
4070                 /* setup FSR0 */
4071                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4072                         pic16_popCopyReg( pic16_stackpnt_lo ), pic16_popCopyReg(&pic16_pc_fsr0l)));
4073
4074                 if(STACK_MODEL_LARGE) {
4075                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
4076                                 pic16_popCopyReg( pic16_stackpnt_hi ), pic16_popCopyReg(&pic16_pc_fsr0h)));
4077                 } else {
4078                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( pic16_stackpnt_hi ));
4079                 }
4080         }
4081                                 
4082 #if 0
4083         /* old code, left here for reference -- VR */    
4084         while (size--) {
4085           char *l ;
4086
4087                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
4088                         /* #NOCHANGE */
4089                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
4090                         pic16_emitpcomment("push %s",l);
4091                         pushed++;
4092                 } else {
4093                         DEBUGpic16_emitcode(";", "%d", __LINE__);
4094                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
4095                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
4096                         
4097                         if (strcmp(fReturn[offset],l)) {
4098                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
4099                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
4100                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4101                                 } else {
4102                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
4103                                 }
4104                                 
4105                                 if(size) {
4106                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
4107                                 }
4108                                 offset++;
4109                         }
4110                 }
4111         }    
4112
4113         if (pushed) {
4114                 while(pushed) {
4115                         pushed--;
4116                         if (strcmp(fReturn[pushed],"a"))
4117                                 pic16_emitcode("pop",fReturn[pushed]);
4118                         else
4119                                 pic16_emitcode("pop","acc");
4120                 }
4121         }
4122 #endif
4123
4124
4125         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
4126     
4127 jumpret:
4128         /* generate a jump to the return label
4129          * if the next is not the return statement */
4130         if (!(ic->next && ic->next->op == LABEL
4131                 && IC_LABEL(ic->next) == returnLabel)) {
4132         
4133                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
4134                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + pic16_labelOffset);
4135         }
4136 }
4137
4138 /*-----------------------------------------------------------------*/
4139 /* genLabel - generates a label                                    */
4140 /*-----------------------------------------------------------------*/
4141 static void genLabel (iCode *ic)
4142 {
4143   FENTRY;
4144
4145   /* special case never generate */
4146   if (IC_LABEL(ic) == entryLabel)
4147     return ;
4148
4149   pic16_emitpLabel(IC_LABEL(ic)->key);
4150 //  pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + pic16_labelOffset));
4151 }
4152
4153 /*-----------------------------------------------------------------*/
4154 /* genGoto - generates a goto                                      */
4155 /*-----------------------------------------------------------------*/
4156 //tsd
4157 static void genGoto (iCode *ic)
4158 {
4159   FENTRY;
4160   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
4161 //  pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+pic16_labelOffset);
4162 }
4163
4164
4165 /*-----------------------------------------------------------------*/
4166 /* genMultbits :- multiplication of bits                           */
4167 /*-----------------------------------------------------------------*/
4168 static void genMultbits (operand *left, 
4169                          operand *right, 
4170                          operand *result)
4171 {
4172   FENTRY;
4173
4174   if(!pic16_sameRegs(AOP(result),AOP(right)))
4175     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
4176
4177   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
4178   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
4179   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
4180
4181 }
4182
4183
4184 /*-----------------------------------------------------------------*/
4185 /* genMultOneByte : 8 bit multiplication & division                */
4186 /*-----------------------------------------------------------------*/
4187 static void genMultOneByte (operand *left,
4188                             operand *right,
4189                             operand *result)
4190 {
4191
4192   FENTRY;
4193   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4194   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4195
4196   /* (if two literals, the value is computed before) */
4197   /* if one literal, literal on the right */
4198   if (AOP_TYPE(left) == AOP_LIT){
4199     operand *t = right;
4200     right = left;
4201     left = t;
4202   }
4203
4204         /* size is already checked in genMult == 1 */
4205 //      size = AOP_SIZE(result);
4206
4207         if (AOP_TYPE(right) == AOP_LIT){
4208                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4209                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4210                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4211                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4212         } else {
4213                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4214                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4215                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4216                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4217         }
4218         
4219         pic16_genMult8X8_8 (left, right,result);
4220 }
4221
4222 /*-----------------------------------------------------------------*/
4223 /* genMultOneWord : 16 bit multiplication                          */
4224 /*-----------------------------------------------------------------*/
4225 static void genMultOneWord (operand *left,
4226                             operand *right,
4227                             operand *result)
4228 {
4229   FENTRY;
4230   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4231   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4232
4233   /* (if two literals, the value is computed before)
4234    * if one literal, literal on the right */
4235   if (AOP_TYPE(left) == AOP_LIT){
4236     operand *t = right;
4237     right = left;
4238     left = t;
4239   }
4240
4241   /* size is checked already == 2 */
4242 //  size = AOP_SIZE(result);
4243
4244   if (AOP_TYPE(right) == AOP_LIT) {
4245     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4246       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4247       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4248       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4249   } else {
4250     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4251       pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4252       pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4253       pic16_aopGet(AOP(result),0,FALSE,FALSE));
4254   }
4255         
4256   pic16_genMult16X16_16(left, right,result);
4257 }
4258
4259 /*-----------------------------------------------------------------*/
4260 /* genMultOneLong : 32 bit multiplication                          */
4261 /*-----------------------------------------------------------------*/
4262 static void genMultOneLong (operand *left,
4263                             operand *right,
4264                             operand *result)
4265 {
4266   FENTRY;
4267   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4268   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
4269
4270   /* (if two literals, the value is computed before)
4271    * if one literal, literal on the right */
4272   if (AOP_TYPE(left) == AOP_LIT){
4273     operand *t = right;
4274     right = left;
4275     left = t;
4276   }
4277
4278   /* size is checked already == 4 */
4279 //  size = AOP_SIZE(result);
4280
4281   if (AOP_TYPE(right) == AOP_LIT) {
4282     pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
4283         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4284         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4285         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4286   } else {
4287     pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
4288         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
4289         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
4290         pic16_aopGet(AOP(result),0,FALSE,FALSE));
4291   }
4292         
4293   pic16_genMult32X32_32(left, right,result);
4294 }
4295
4296
4297
4298 /*-----------------------------------------------------------------*/
4299 /* genMult - generates code for multiplication                     */
4300 /*-----------------------------------------------------------------*/
4301 static void genMult (iCode *ic)
4302 {
4303   operand *left = IC_LEFT(ic);
4304   operand *right = IC_RIGHT(ic);
4305   operand *result= IC_RESULT(ic);   
4306
4307     FENTRY;
4308         /* assign the amsops */
4309         pic16_aopOp (left,ic,FALSE);
4310         pic16_aopOp (right,ic,FALSE);
4311         pic16_aopOp (result,ic,TRUE);
4312
4313         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4314
4315         /* special cases first *
4316         * both are bits */
4317         if (AOP_TYPE(left) == AOP_CRY
4318                 && AOP_TYPE(right)== AOP_CRY) {
4319                 genMultbits(left,right,result);
4320           goto release ;
4321         }
4322
4323         /* if both are of size == 1 */
4324         if(AOP_SIZE(left) == 1
4325                 && AOP_SIZE(right) == 1) {
4326                 genMultOneByte(left,right,result);
4327           goto release ;
4328         }
4329
4330         /* if both are of size == 2 */
4331         if(AOP_SIZE(left) == 2
4332                 && AOP_SIZE(right) == 2) {
4333                 genMultOneWord(left, right, result);
4334           goto release;
4335         }
4336         
4337         /* if both are of size == 4 */
4338         if(AOP_SIZE(left) == 4
4339                 && AOP_SIZE(right) == 4) {
4340                 genMultOneLong(left, right, result);
4341           goto release;
4342         }
4343         
4344         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
4345
4346
4347         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
4348         /* should have been converted to function call */
4349         assert(0) ;
4350
4351 release :
4352         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4353         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4354         pic16_freeAsmop(result,NULL,ic,TRUE); 
4355 }
4356
4357 /*-----------------------------------------------------------------*/
4358 /* genDivbits :- division of bits                                  */
4359 /*-----------------------------------------------------------------*/
4360 static void genDivbits (operand *left, 
4361                         operand *right, 
4362                         operand *result)
4363 {
4364   char *l;
4365
4366     FENTRY;
4367     /* the result must be bit */    
4368     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4369     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4370
4371     MOVA(l);    
4372
4373     pic16_emitcode("div","ab");
4374     pic16_emitcode("rrc","a");
4375     pic16_aopPut(AOP(result),"c",0);
4376 }
4377
4378 /*-----------------------------------------------------------------*/
4379 /* genDivOneByte : 8 bit division                                  */
4380 /*-----------------------------------------------------------------*/
4381 static void genDivOneByte (operand *left,
4382                            operand *right,
4383                            operand *result)
4384 {
4385   sym_link *opetype = operandType(result);
4386   char *l ;
4387   symbol *lbl ;
4388   int size,offset;
4389
4390         /* result = divident / divisor
4391          * - divident may be a register or a literal,
4392          * - divisor may be a register or a literal,
4393          * so there are 3 cases (literal / literal is optimized
4394          * by the front-end) to handle.
4395          * In addition we must handle signed and unsigned, which
4396          * result in 6 final different cases -- VR */
4397
4398     FENTRY;
4399     
4400     size = AOP_SIZE(result) - 1;
4401     offset = 1;
4402     /* signed or unsigned */
4403     if (SPEC_USIGN(opetype)) {
4404       pCodeOp *pct1,    /* count */
4405                 *pct2,  /* reste */
4406                 *pct3;  /* temp */
4407       symbol *label1, *label2, *label3;;
4408
4409
4410         /* unsigned is easy */
4411
4412         pct1 = pic16_popGetTempReg(1);
4413         pct2 = pic16_popGetTempReg(1);
4414         pct3 = pic16_popGetTempReg(1);
4415         
4416         label1 = newiTempLabel(NULL);
4417         label2 = newiTempLabel(NULL);
4418         label3 = newiTempLabel(NULL);
4419
4420         /* the following algorithm is extracted from divuint.c */
4421
4422         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4423         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4424         
4425         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4426
4427         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4428         
4429         pic16_emitpLabel(label1->key);
4430         
4431         emitCLRC;
4432         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4433
4434
4435         emitCLRC;
4436         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4437         
4438
4439         emitSKPNC;
4440         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4441         
4442         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4443         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4444         
4445         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4446         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4447         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4448         
4449         pic16_emitpLabel( label3->key );
4450         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4451         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4452         
4453         
4454
4455         pic16_emitpLabel(label2->key);
4456         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4457         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4458         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4459         
4460         /* result is in wreg */
4461         if(AOP_TYPE(result) != AOP_ACC)
4462                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4463
4464         pic16_popReleaseTempReg( pct3, 1);
4465         pic16_popReleaseTempReg( pct2, 1);
4466         pic16_popReleaseTempReg( pct1, 1);
4467
4468         return ;
4469     }
4470
4471     /* signed is a little bit more difficult */
4472
4473     /* save the signs of the operands */
4474     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4475     MOVA(l);    
4476     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4477     pic16_emitcode("push","acc"); /* save it on the stack */
4478
4479     /* now sign adjust for both left & right */
4480     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4481     MOVA(l);       
4482     lbl = newiTempLabel(NULL);
4483     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4484     pic16_emitcode("cpl","a");   
4485     pic16_emitcode("inc","a");
4486     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4487     pic16_emitcode("mov","b,a");
4488
4489     /* sign adjust left side */
4490     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4491     MOVA(l);
4492
4493     lbl = newiTempLabel(NULL);
4494     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4495     pic16_emitcode("cpl","a");
4496     pic16_emitcode("inc","a");
4497     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4498
4499     /* now the division */
4500     pic16_emitcode("div","ab");
4501     /* we are interested in the lower order
4502     only */
4503     pic16_emitcode("mov","b,a");
4504     lbl = newiTempLabel(NULL);
4505     pic16_emitcode("pop","acc");   
4506     /* if there was an over flow we don't 
4507     adjust the sign of the result */
4508     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4509     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4510     CLRC;
4511     pic16_emitcode("clr","a");
4512     pic16_emitcode("subb","a,b");
4513     pic16_emitcode("mov","b,a");
4514     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4515
4516     /* now we are done */
4517     pic16_aopPut(AOP(result),"b",0);
4518     if(size > 0){
4519         pic16_emitcode("mov","c,b.7");
4520         pic16_emitcode("subb","a,acc");   
4521     }
4522     while (size--)
4523         pic16_aopPut(AOP(result),"a",offset++);
4524
4525 }
4526
4527 /*-----------------------------------------------------------------*/
4528 /* genDiv - generates code for division                            */
4529 /*-----------------------------------------------------------------*/
4530 static void genDiv (iCode *ic)
4531 {
4532     operand *left = IC_LEFT(ic);
4533     operand *right = IC_RIGHT(ic);
4534     operand *result= IC_RESULT(ic);   
4535
4536
4537         /* Division is a very lengthy algorithm, so it is better
4538          * to call support routines than inlining algorithm.
4539          * Division functions written here just in case someone
4540          * wants to inline and not use the support libraries -- VR */
4541
4542     FENTRY;
4543     
4544     /* assign the amsops */
4545     pic16_aopOp (left,ic,FALSE);
4546     pic16_aopOp (right,ic,FALSE);
4547     pic16_aopOp (result,ic,TRUE);
4548
4549     /* special cases first */
4550     /* both are bits */
4551     if (AOP_TYPE(left) == AOP_CRY &&
4552         AOP_TYPE(right)== AOP_CRY) {
4553         genDivbits(left,right,result);
4554         goto release ;
4555     }
4556
4557     /* if both are of size == 1 */
4558     if (AOP_SIZE(left) == 1 &&
4559         AOP_SIZE(right) == 1 ) {
4560         genDivOneByte(left,right,result);
4561         goto release ;
4562     }
4563
4564     /* should have been converted to function call */
4565     assert(0);
4566 release :
4567     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4568     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4569     pic16_freeAsmop(result,NULL,ic,TRUE); 
4570 }
4571
4572 /*-----------------------------------------------------------------*/
4573 /* genModbits :- modulus of bits                                   */
4574 /*-----------------------------------------------------------------*/
4575 static void genModbits (operand *left, 
4576                         operand *right, 
4577                         operand *result)
4578 {
4579   char *l;
4580
4581     FENTRY;  
4582     
4583     werror(W_POSSBUG2, __FILE__, __LINE__);
4584     /* the result must be bit */    
4585     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4586     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4587
4588     MOVA(l);       
4589
4590     pic16_emitcode("div","ab");
4591     pic16_emitcode("mov","a,b");
4592     pic16_emitcode("rrc","a");
4593     pic16_aopPut(AOP(result),"c",0);
4594 }
4595
4596 /*-----------------------------------------------------------------*/
4597 /* genModOneByte : 8 bit modulus                                   */
4598 /*-----------------------------------------------------------------*/
4599 static void genModOneByte (operand *left,
4600                            operand *right,
4601                            operand *result)
4602 {
4603   sym_link *opetype = operandType(result);
4604   char *l ;
4605   symbol *lbl ;
4606
4607     FENTRY;
4608     werror(W_POSSBUG2, __FILE__, __LINE__);
4609
4610     /* signed or unsigned */
4611     if (SPEC_USIGN(opetype)) {
4612         /* unsigned is easy */
4613         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4614         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4615         MOVA(l);    
4616         pic16_emitcode("div","ab");
4617         pic16_aopPut(AOP(result),"b",0);
4618         return ;
4619     }
4620
4621     /* signed is a little bit more difficult */
4622
4623     /* save the signs of the operands */
4624     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4625     MOVA(l);
4626
4627     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4628     pic16_emitcode("push","acc"); /* save it on the stack */
4629
4630     /* now sign adjust for both left & right */
4631     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4632     MOVA(l);
4633
4634     lbl = newiTempLabel(NULL);
4635     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4636     pic16_emitcode("cpl","a");   
4637     pic16_emitcode("inc","a");
4638     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4639     pic16_emitcode("mov","b,a"); 
4640
4641     /* sign adjust left side */
4642     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4643     MOVA(l);
4644
4645     lbl = newiTempLabel(NULL);
4646     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4647     pic16_emitcode("cpl","a");   
4648     pic16_emitcode("inc","a");
4649     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4650
4651     /* now the multiplication */
4652     pic16_emitcode("div","ab");
4653     /* we are interested in the lower order
4654     only */
4655     lbl = newiTempLabel(NULL);
4656     pic16_emitcode("pop","acc");   
4657     /* if there was an over flow we don't 
4658     adjust the sign of the result */
4659     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4660     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4661     CLRC ;
4662     pic16_emitcode("clr","a");
4663     pic16_emitcode("subb","a,b");
4664     pic16_emitcode("mov","b,a");
4665     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4666
4667     /* now we are done */
4668     pic16_aopPut(AOP(result),"b",0);
4669
4670 }
4671
4672 /*-----------------------------------------------------------------*/
4673 /* genMod - generates code for division                            */
4674 /*-----------------------------------------------------------------*/
4675 static void genMod (iCode *ic)
4676 {
4677   operand *left = IC_LEFT(ic);
4678   operand *right = IC_RIGHT(ic);
4679   operand *result= IC_RESULT(ic);  
4680
4681     FENTRY;
4682     
4683     /* assign the amsops */
4684     pic16_aopOp (left,ic,FALSE);
4685     pic16_aopOp (right,ic,FALSE);
4686     pic16_aopOp (result,ic,TRUE);
4687
4688     /* special cases first */
4689     /* both are bits */
4690     if (AOP_TYPE(left) == AOP_CRY &&
4691         AOP_TYPE(right)== AOP_CRY) {
4692         genModbits(left,right,result);
4693         goto release ;
4694     }
4695
4696     /* if both are of size == 1 */
4697     if (AOP_SIZE(left) == 1 &&
4698         AOP_SIZE(right) == 1 ) {
4699         genModOneByte(left,right,result);
4700         goto release ;
4701     }
4702
4703     /* should have been converted to function call */
4704     assert(0);
4705
4706 release :
4707     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4708     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4709     pic16_freeAsmop(result,NULL,ic,TRUE); 
4710 }
4711
4712 /*-----------------------------------------------------------------*/
4713 /* genIfxJump :- will create a jump depending on the ifx           */
4714 /*-----------------------------------------------------------------*/
4715 /*
4716   note: May need to add parameter to indicate when a variable is in bit space.
4717 */
4718 static void genIfxJump (iCode *ic, char *jval)
4719 {
4720   FENTRY;
4721   
4722     /* if true label then we jump if condition
4723     supplied is true */
4724     if ( IC_TRUE(ic) ) {
4725
4726         if(strcmp(jval,"a") == 0)
4727           emitSKPZ;
4728         else if (strcmp(jval,"c") == 0)
4729           emitSKPNC;
4730         else {
4731           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4732           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4733         }
4734
4735         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4736         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4737
4738     }
4739     else {
4740         /* false label is present */
4741         if(strcmp(jval,"a") == 0)
4742           emitSKPNZ;
4743         else if (strcmp(jval,"c") == 0)
4744           emitSKPC;
4745         else {
4746           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4747           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1, PO_GPR_REGISTER));
4748         }
4749
4750         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4751         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4752
4753     }
4754
4755
4756     /* mark the icode as generated */
4757     ic->generated = 1;
4758 }
4759
4760 static void genIfxpCOpJump (iCode *ic, pCodeOp *jop)
4761 {
4762   FENTRY;
4763   
4764     /* if true label then we jump if condition
4765     supplied is true */
4766     if ( IC_TRUE(ic) ) {
4767       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);     
4768       pic16_emitpcode(POC_BTFSC, jop);
4769
4770       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4771       pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + pic16_labelOffset);
4772
4773     } else {
4774       /* false label is present */
4775       DEBUGpic16_emitcode ("; ***","%d - assuming is in bit space",__LINE__);
4776       pic16_emitpcode(POC_BTFSS, jop);
4777           
4778       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4779       pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + pic16_labelOffset);
4780     }
4781
4782
4783     /* mark the icode as generated */
4784     ic->generated = 1;
4785 }
4786
4787 #if 0
4788 // not needed ATM
4789
4790 /*-----------------------------------------------------------------*/
4791 /* genSkip                                                         */
4792 /*-----------------------------------------------------------------*/
4793 static void genSkip(iCode *ifx,int status_bit)
4794 {
4795   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4796   if(!ifx)
4797     return;
4798
4799   if ( IC_TRUE(ifx) ) {
4800     switch(status_bit) {
4801     case 'z':
4802       emitSKPNZ;
4803       break;
4804
4805     case 'c':
4806       emitSKPNC;
4807       break;
4808
4809     case 'd':
4810       emitSKPDC;
4811       break;
4812
4813     }
4814
4815     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4816     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4817
4818   } else {
4819
4820     switch(status_bit) {
4821
4822     case 'z':
4823       emitSKPZ;
4824       break;
4825
4826     case 'c':
4827       emitSKPC;
4828       break;
4829
4830     case 'd':
4831       emitSKPDC;
4832       break;
4833     }
4834     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4835     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4836
4837   }
4838
4839 }
4840 #endif
4841
4842 /*-----------------------------------------------------------------*/
4843 /* genSkipc                                                        */
4844 /*-----------------------------------------------------------------*/
4845 static void genSkipc(resolvedIfx *rifx)
4846 {
4847   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4848   
4849   if(!rifx)
4850     return;
4851
4852   if(rifx->condition)
4853     emitSKPNC;
4854   else
4855     emitSKPC;
4856
4857   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4858   rifx->generated = 1;
4859 }
4860
4861 #if !(USE_SIMPLE_GENCMP)
4862 /*-----------------------------------------------------------------*/
4863 /* genSkipz2                                                       */
4864 /*-----------------------------------------------------------------*/
4865 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4866 {
4867   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4868   
4869   if(!rifx)
4870     return;
4871
4872   if( (rifx->condition ^ invert_condition) & 1)
4873     emitSKPZ;
4874   else
4875     emitSKPNZ;
4876
4877   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4878   rifx->generated = 1;
4879 }
4880 #endif
4881
4882 #if 0
4883 /*-----------------------------------------------------------------*/
4884 /* genSkipz                                                        */
4885 /*-----------------------------------------------------------------*/
4886 static void genSkipz(iCode *ifx, int condition)
4887 {
4888   if(!ifx)
4889     return;
4890
4891   if(condition)
4892     emitSKPNZ;
4893   else
4894     emitSKPZ;
4895
4896   if ( IC_TRUE(ifx) )
4897     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4898   else
4899     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4900
4901   if ( IC_TRUE(ifx) )
4902     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
4903   else
4904     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
4905
4906 }
4907 #endif
4908
4909 #if !(USE_SIMPLE_GENCMP)
4910 /*-----------------------------------------------------------------*/
4911 /* genSkipCond                                                     */
4912 /*-----------------------------------------------------------------*/
4913 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4914 {
4915   if(!rifx)
4916     return;
4917
4918   if(rifx->condition)
4919     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4920   else
4921     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER));
4922
4923
4924   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4925   rifx->generated = 1;
4926 }
4927 #endif
4928
4929 #if 0
4930 /*-----------------------------------------------------------------*/
4931 /* genChkZeroes :- greater or less than comparison                 */
4932 /*     For each byte in a literal that is zero, inclusive or the   */
4933 /*     the corresponding byte in the operand with W                */
4934 /*     returns true if any of the bytes are zero                   */
4935 /*-----------------------------------------------------------------*/
4936 static int genChkZeroes(operand *op, int lit,  int size)
4937 {
4938
4939   int i;
4940   int flag =1;
4941
4942   while(size--) {
4943     i = (lit >> (size*8)) & 0xff;
4944
4945     if(i==0) {
4946       if(flag) 
4947         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4948       else
4949         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4950       flag = 0;
4951     }
4952   }
4953
4954   return (flag==0);
4955 }
4956 #endif
4957
4958
4959 /*-----------------------------------------------------------------*/
4960 /* mov2w_regOrLit :- move to WREG either the offset's byte from    */
4961 /*                  aop (if it's NOT a literal) or from lit (if    */
4962 /*                  aop is a literal)                              */
4963 /*-----------------------------------------------------------------*/
4964 void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) {
4965   if (aop->type == AOP_LIT) {
4966     pic16_emitpcode (POC_MOVLW, pic16_popGetLit(lit >> (offset*8)));
4967   } else {
4968     pic16_emitpcode (POC_MOVFW, pic16_popGet (aop, offset));
4969   }
4970 }
4971
4972 /*-----------------------------------------------------------------*/
4973 /* genCmp :- greater or less than comparison                       */
4974 /*-----------------------------------------------------------------*/
4975
4976 #if USE_SIMPLE_GENCMP           /* { */
4977
4978 /* genCmp performs a left < right comparison, stores
4979  * the outcome in result (if != NULL) and generates
4980  * control flow code for the ifx (if != NULL).
4981  *
4982  * This version leaves in sequences like
4983  * "B[CS]F STATUS,0; BTFS[CS] STATUS,0"
4984  * which should be optmized by the peephole
4985  * optimizer - RN 2005-01-01 */
4986 static void genCmp (operand *left,operand *right,
4987                     operand *result, iCode *ifx, int sign)
4988 {
4989   resolvedIfx rIfx;
4990   int size;
4991   int offs;
4992   symbol *templbl;
4993   operand *dummy;
4994   unsigned long lit;
4995   unsigned long mask;
4996   int performedLt;
4997
4998   FENTRY;
4999   
5000   assert (left && right);
5001   assert (AOP_SIZE(left) == AOP_SIZE(right));
5002
5003   size = AOP_SIZE(right) - 1;
5004   mask = (0x100UL << (size*8)) - 1;
5005   // in the end CARRY holds "left < right" (performedLt == 1) or "left >= right" (performedLt == 0)
5006   performedLt = 1;
5007   templbl = NULL;
5008   lit = 0;
5009   
5010   resolveIfx (&rIfx, ifx);
5011
5012   /* handle for special cases */
5013   if(pic16_genCmp_special(left, right, result, ifx, &rIfx, sign))
5014       return;
5015
5016   /**********************************************************************
5017    * handle bits - bit compares are promoted to int compares seemingly! *
5018    **********************************************************************/
5019 #if 0
5020   // THIS IS COMPLETELY UNTESTED!
5021   if (AOP_TYPE(left) == AOP_CRY && AOP_TYPE(right) == AOP_CRY) {
5022     pCodeOp *pcleft = pic16_popGet(AOP(left), 0);
5023     pCodeOp *pcright = pic16_popGet(AOP(right), 0);
5024     assert (pcleft->type == PO_GPR_BIT && pcright->type == PO_GPR_BIT);
5025
5026     emitSETC;
5027     // 1 < {0,1} is false --> clear C by skipping the next instruction
5028     //pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (AOP(left),0), PCORB(pcleft)->bit);
5029     pic16_emitpcode (POC_BTFSS, pic16_popGet (AOP(left), 0));
5030     // {0,1} < 0 is false --> clear C by NOT skipping the next instruction
5031     pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit (pic16_popGet(AOP(right),0), PCORB(pcright)->bit));
5032     emitCLRC; // only skipped for left=0 && right=1
5033
5034     goto correct_result_in_carry;
5035   } // if
5036 #endif
5037
5038   /*************************************************
5039    * make sure that left is register (or the like) *
5040    *************************************************/
5041   if (!isAOP_REGlike(left)) {
5042     DEBUGpc ("swapping arguments (AOP_TYPEs %d/%d)", AOP_TYPE(left), AOP_TYPE(right));
5043     assert (isAOP_LIT(left));
5044     assert (isAOP_REGlike(right));
5045     // swap left and right
5046     // left < right <==> right > left <==> (right >= left + 1)
5047     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5048
5049     if ( (!sign && (lit & mask) == mask) || (sign && (lit & mask) == (mask >> 1)) ) {
5050       // MAXVALUE < right? always false
5051       if (performedLt) emitCLRC; else emitSETC;
5052       goto correct_result_in_carry;
5053     } // if
5054
5055     // This fails for lit = 0xFF (unsigned) AND lit = 0x7F (signed),
5056     // that's why we handled it above.
5057     lit++;
5058
5059     dummy = left;
5060     left = right;
5061     right = dummy;
5062
5063     performedLt ^= 1; // instead of "left < right" we check for "right >= left+1, i.e. "right < left+1"
5064   } else if (isAOP_LIT(right)) {
5065     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5066   } // if
5067
5068   assert (isAOP_REGlike(left)); // left must be register or the like
5069   assert (isAOP_REGlike(right) || isAOP_LIT(right)); // right may be register-like or a literal
5070
5071   /*************************************************
5072    * special cases go here                         *
5073    *************************************************/
5074
5075   if (isAOP_LIT(right)) {
5076     if (!sign) {
5077       // unsigned comparison to a literal
5078       DEBUGpc ("unsigned compare: left %s lit(0x%X=%lu), size=%d", performedLt ? "<" : ">=", lit, lit, size+1);
5079       if (lit == 0) {
5080         // unsigned left < 0? always false
5081         if (performedLt) emitCLRC; else emitSETC;
5082         goto correct_result_in_carry;
5083       }
5084     } else {
5085       // signed comparison to a literal
5086       DEBUGpc ("signed compare: left %s lit(0x%X=%ld), size=%d, mask=%x", performedLt ? "<" : ">=", lit, lit, size+1, mask);
5087       if ((lit & mask) == ((0x80 << (size*8)) & mask)) {
5088         // signed left < 0x80000000? always false
5089         if (performedLt) emitCLRC; else emitSETC;
5090         goto correct_result_in_carry;
5091       } else if (lit == 0) {
5092         // compare left < 0; set CARRY if SIGNBIT(left) is set
5093         if (performedLt) emitSETC; else emitCLRC;
5094         pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet (AOP(left), size), 7));
5095         if (performedLt) emitCLRC; else emitSETC;
5096         goto correct_result_in_carry;
5097       }
5098     } // if (!sign)
5099   } // right is literal
5100
5101   /*************************************************
5102    * perform a general case comparison             *
5103    * make sure we get CARRY==1 <==> left >= right  *
5104    *************************************************/
5105   // compare most significant bytes
5106   //DEBUGpc ("comparing bytes at offset %d", size);
5107   if (!sign) {
5108     // unsigned comparison
5109     mov2w_regOrLit (AOP(right), lit, size);
5110     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), size));
5111   } else {
5112     // signed comparison
5113     // (add 2^n to both operands then perform an unsigned comparison)
5114     if (isAOP_LIT(right)) {
5115       // left >= LIT <-> LIT-left <= 0 <-> LIT-left == 0 OR !(LIT-left >= 0)
5116       unsigned char litbyte = (lit >> (8*size)) & 0xFF;
5117
5118       if (litbyte == 0x80) {
5119         // left >= 0x80 -- always true, but more bytes to come
5120         pic16_mov2w (AOP(left), size);
5121         pic16_emitpcode (POC_XORLW, pic16_popGetLit (0x80)); // set ZERO flag
5122         emitSETC;
5123       } else {
5124         // left >= LIT <-> left + (-LIT) >= 0 <-> left + (0x100-LIT) >= 0x100
5125         pic16_mov2w (AOP(left), size);
5126         pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5127         pic16_emitpcode (POC_ADDLW, pic16_popGetLit ((0x100 - (litbyte + 0x80)) & 0x00FF));
5128       } // if
5129     } else {
5130       /* using PRODL as a temporary register here */
5131       pCodeOp *pctemp = pic16_popCopyReg(&pic16_pc_prodl);
5132       //pCodeOp *pctemp = pic16_popGetTempReg(1);
5133       pic16_mov2w (AOP(left), size);
5134       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5135       pic16_emitpcode (POC_MOVWF, pctemp);
5136       pic16_mov2w (AOP(right), size);
5137       pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x80));
5138       pic16_emitpcode (POC_SUBFW, pctemp);
5139       //pic16_popReleaseTempReg(pctemp, 1);
5140     }
5141   } // if (!sign)
5142
5143   // compare remaining bytes (treat as unsigned case from above)
5144   templbl = newiTempLabel ( NULL );
5145   offs = size;
5146   while (offs--) {
5147     //DEBUGpc ("comparing bytes at offset %d", offs);
5148     pic16_emitpcode (POC_BNZ, pic16_popGetLabel (templbl->key));
5149     mov2w_regOrLit (AOP(right), lit, offs);
5150     pic16_emitpcode (POC_SUBFW, pic16_popGet (AOP(left), offs));
5151   } // while (offs)
5152   pic16_emitpLabel (templbl->key);
5153   goto result_in_carry;
5154
5155 result_in_carry:
5156   
5157   /****************************************************
5158    * now CARRY contains the result of the comparison: *
5159    * SUBWF sets CARRY iff                             *
5160    * F-W >= 0 <==> F >= W <==> !(F < W)               *
5161    * (F=left, W=right)                                *
5162    ****************************************************/
5163
5164   if (performedLt) {
5165     if (result && AOP_TYPE(result) != AOP_CRY) {
5166       // value will be stored
5167       emitTOGC;
5168     } else {
5169       // value wil only be used in the following genSkipc()
5170       rIfx.condition ^= 1;
5171     }
5172   } // if
5173
5174 correct_result_in_carry:
5175
5176   // assign result to variable (if neccessary)
5177   if (result && AOP_TYPE(result) != AOP_CRY) {
5178     //DEBUGpc ("assign result");
5179     size = AOP_SIZE(result);
5180     while (size--) {
5181       pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), size));
5182     } // while
5183     pic16_emitpcode (POC_RLCF, pic16_popGet (AOP(result), 0));
5184   } // if (result)
5185
5186   // perform conditional jump
5187   if (ifx) {
5188     //DEBUGpc ("generate control flow");
5189     genSkipc (&rIfx);
5190     ifx->generated = 1;
5191   } // if
5192 }
5193
5194 #elif 1         /* } */
5195                 /* { */
5196       /* original code */
5197 static void genCmp (operand *left,operand *right,
5198                     operand *result, iCode *ifx, int sign)
5199 {
5200   int size; //, offset = 0 ;
5201   unsigned long lit = 0L,i = 0;
5202   resolvedIfx rFalseIfx;
5203   //  resolvedIfx rTrueIfx;
5204   symbol *truelbl;
5205   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5206 /*
5207   if(ifx) {
5208     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
5209     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
5210   }
5211 */
5212
5213   FENTRY;
5214   
5215   resolveIfx(&rFalseIfx,ifx);
5216   truelbl  = newiTempLabel(NULL);
5217   size = max(AOP_SIZE(left),AOP_SIZE(right));
5218
5219   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5220
5221 #define _swapp
5222
5223   /* if literal is on the right then swap with left */
5224   if ((AOP_TYPE(right) == AOP_LIT)) {
5225     operand *tmp = right ;
5226     unsigned long mask = (0x100 << (8*(size-1))) - 1;
5227     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5228 #ifdef _swapp
5229
5230     lit = (lit - 1) & mask;
5231     right = left;
5232     left = tmp;
5233     rFalseIfx.condition ^= 1;
5234 #endif
5235
5236   } else if ((AOP_TYPE(left) == AOP_LIT)) {
5237     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
5238   }
5239
5240
5241   //if(IC_TRUE(ifx) == NULL)
5242   /* if left & right are bit variables */
5243   if (AOP_TYPE(left) == AOP_CRY &&
5244       AOP_TYPE(right) == AOP_CRY ) {
5245     assert (0 && "bit variables used in genCmp");
5246     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5247     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
5248   } else {
5249     /* subtract right from left if at the
5250        end the carry flag is set then we know that
5251        left is greater than right */
5252
5253     symbol *lbl  = newiTempLabel(NULL);
5254
5255 #if 0
5256         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
5257                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset);
5258 #endif
5259
5260 #ifndef _swapp
5261     if(AOP_TYPE(right) == AOP_LIT) {
5262
5263       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5264
5265       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
5266
5267       /* special cases */
5268
5269       if(lit == 0) {
5270
5271         if(sign != 0) 
5272           genSkipCond(&rFalseIfx,left,size-1,7);
5273         else 
5274           /* no need to compare to 0...*/
5275           /* NOTE: this is a de-generate compare that most certainly 
5276            *       creates some dead code. */
5277           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5278
5279         if(ifx) ifx->generated = 1;
5280         return;
5281
5282       }
5283       size--;
5284
5285       if(size == 0) {
5286         //i = (lit >> (size*8)) & 0xff;
5287         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5288         
5289         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5290
5291         i = ((0-lit) & 0xff);
5292         if(sign) {
5293           if( i == 0x81) { 
5294             /* lit is 0x7f, all signed chars are less than
5295              * this except for 0x7f itself */
5296             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5297             genSkipz2(&rFalseIfx,0);
5298           } else {
5299             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5300             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
5301             genSkipc(&rFalseIfx);
5302           }
5303
5304         } else {
5305           if(lit == 1) {
5306             genSkipz2(&rFalseIfx,1);
5307           } else {
5308             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
5309             genSkipc(&rFalseIfx);
5310           }
5311         }
5312
5313         if(ifx) ifx->generated = 1;
5314         return;
5315       }
5316
5317       /* chars are out of the way. now do ints and longs */
5318
5319
5320       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
5321         
5322       /* special cases */
5323
5324       if(sign) {
5325
5326         if(lit == 0) {
5327           genSkipCond(&rFalseIfx,left,size,7);
5328           if(ifx) ifx->generated = 1;
5329           return;
5330         }
5331
5332         if(lit <0x100) {
5333           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5334
5335           //rFalseIfx.condition ^= 1;
5336           //genSkipCond(&rFalseIfx,left,size,7);
5337           //rFalseIfx.condition ^= 1;
5338
5339           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5340           if(rFalseIfx.condition)
5341             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5342           else
5343             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5344
5345           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
5346           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5347           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
5348
5349           while(size > 1)
5350             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
5351
5352           if(rFalseIfx.condition) {
5353             emitSKPZ;
5354             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5355
5356           } else {
5357             emitSKPNZ;
5358           }
5359
5360           genSkipc(&rFalseIfx);
5361           pic16_emitpLabel(truelbl->key);
5362           if(ifx) ifx->generated = 1;
5363           return;
5364
5365         }
5366
5367         if(size == 1) {
5368
5369           if( (lit & 0xff) == 0) {
5370             /* lower byte is zero */
5371             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5372             i = ((lit >> 8) & 0xff) ^0x80;
5373             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5374             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5375             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5376             genSkipc(&rFalseIfx);
5377
5378
5379             if(ifx) ifx->generated = 1;
5380             return;
5381
5382           }
5383         } else {
5384           /* Special cases for signed longs */
5385           if( (lit & 0xffffff) == 0) {
5386             /* lower byte is zero */
5387             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5388             i = ((lit >> 8*3) & 0xff) ^0x80;
5389             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5390             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5391             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5392             genSkipc(&rFalseIfx);
5393
5394
5395             if(ifx) ifx->generated = 1;
5396             return;
5397
5398           }
5399
5400         }
5401
5402
5403         if(lit & (0x80 << (size*8))) {
5404           /* lit is negative */
5405           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5406
5407           //genSkipCond(&rFalseIfx,left,size,7);
5408
5409           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5410
5411           if(rFalseIfx.condition)
5412             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5413           else
5414             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5415
5416
5417         } else {
5418           /* lit is positive */
5419           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
5420           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5421           if(rFalseIfx.condition)
5422             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5423           else
5424             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5425
5426         }
5427
5428         /*
5429           This works, but is only good for ints.
5430           It also requires a "known zero" register.
5431           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
5432           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
5433           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
5434           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
5435           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
5436           genSkipc(&rFalseIfx);
5437
5438           pic16_emitpLabel(truelbl->key);
5439           if(ifx) ifx->generated = 1;
5440           return;
5441         **/
5442           
5443         /* There are no more special cases, so perform a general compare */
5444   
5445         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5446         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5447
5448         while(size--) {
5449
5450           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
5451           emitSKPNZ;
5452           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5453         }
5454         //rFalseIfx.condition ^= 1;
5455         genSkipc(&rFalseIfx);
5456
5457         pic16_emitpLabel(truelbl->key);
5458
5459         if(ifx) ifx->generated = 1;
5460         return;
5461
5462
5463       }
5464
5465
5466       /* sign is out of the way. So now do an unsigned compare */
5467       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
5468
5469
5470       /* General case - compare to an unsigned literal on the right.*/
5471
5472       i = (lit >> (size*8)) & 0xff;
5473       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5474       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5475       while(size--) {
5476         i = (lit >> (size*8)) & 0xff;
5477
5478         if(i) {
5479           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5480           emitSKPNZ;
5481           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5482         } else {
5483           /* this byte of the lit is zero, 
5484            *if it's not the last then OR in the variable */
5485           if(size)
5486             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
5487         }
5488       }
5489
5490
5491       pic16_emitpLabel(lbl->key);
5492 //      pic16_emitpLabel(truelbl->key);
5493       //if(emitFinalCheck)
5494       genSkipc(&rFalseIfx);
5495       if(sign)
5496         pic16_emitpLabel(truelbl->key);
5497
5498       if(ifx) ifx->generated = 1;
5499       return;
5500
5501
5502     }
5503 #endif  // _swapp
5504
5505     if(AOP_TYPE(left) == AOP_LIT) {
5506       //symbol *lbl = newiTempLabel(NULL);
5507
5508       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
5509
5510
5511       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
5512
5513       /* Special cases */
5514       if((lit == 0) && (sign == 0)){
5515
5516         size--;
5517         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5518         while(size) 
5519           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
5520
5521         genSkipz2(&rFalseIfx,0);
5522         if(ifx) ifx->generated = 1;
5523         return;
5524       }
5525
5526       if(size==1) {
5527         /* Special cases */
5528         lit &= 0xff;
5529         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
5530           /* degenerate compare can never be true */
5531           if(rFalseIfx.condition == 0)
5532             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
5533
5534           if(ifx) ifx->generated = 1;
5535           return;
5536         }
5537
5538         if(sign) {
5539           /* signed comparisons to a literal byte */
5540
5541           int lp1 = (lit+1) & 0xff;
5542
5543           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
5544           switch (lp1) {
5545           case 0:
5546             rFalseIfx.condition ^= 1;
5547             genSkipCond(&rFalseIfx,right,0,7);
5548             break;
5549           case 0x7f:
5550             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5551             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
5552             genSkipz2(&rFalseIfx,1);
5553             break;
5554           default:
5555             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5556             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5557             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
5558             rFalseIfx.condition ^= 1;
5559             genSkipc(&rFalseIfx);
5560             break;
5561           }
5562         } else {
5563           /* unsigned comparisons to a literal byte */
5564
5565           switch(lit & 0xff ) {
5566           case 0:
5567             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5568             genSkipz2(&rFalseIfx,0);
5569             break;
5570           case 0x7f:
5571             rFalseIfx.condition ^= 1;
5572             genSkipCond(&rFalseIfx,right,0,7);
5573             break;
5574
5575           default:
5576             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
5577             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5578             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5579             rFalseIfx.condition ^= 1;
5580             if (AOP_TYPE(result) == AOP_CRY)
5581               genSkipc(&rFalseIfx);
5582             else {
5583               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5584               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5585             }         
5586             break;
5587           }
5588         }
5589
5590         if(ifx) ifx->generated = 1;
5591         if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5592                 goto check_carry;
5593         return;
5594
5595       } else {
5596
5597         /* Size is greater than 1 */
5598
5599         if(sign) {
5600           int lp1 = lit+1;
5601
5602           size--;
5603
5604           if(lp1 == 0) {
5605             /* this means lit = 0xffffffff, or -1 */
5606
5607
5608             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
5609             rFalseIfx.condition ^= 1;
5610             genSkipCond(&rFalseIfx,right,size,7);
5611             if(ifx) ifx->generated = 1;
5612
5613             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5614               goto check_carry;
5615
5616             return;
5617           }
5618
5619           if(lit == 0) {
5620             int s = size;
5621
5622             if(rFalseIfx.condition) {
5623               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5624               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5625             }
5626
5627             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5628             while(size--)
5629               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5630
5631
5632             emitSKPZ;
5633             if(rFalseIfx.condition) {
5634               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5635               pic16_emitpLabel(truelbl->key);
5636             }else {
5637               rFalseIfx.condition ^= 1;
5638               genSkipCond(&rFalseIfx,right,s,7);
5639             }
5640
5641             if(ifx) ifx->generated = 1;
5642
5643             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5644               goto check_carry;
5645
5646             return;
5647           }
5648
5649           if((size == 1) &&  (0 == (lp1&0xff))) {
5650             /* lower byte of signed word is zero */
5651             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
5652             i = ((lp1 >> 8) & 0xff) ^0x80;
5653             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5654             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
5655             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
5656
5657             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) {
5658               emitTOGC;
5659               if(ifx) ifx->generated = 1;
5660               goto check_carry;
5661             } else {
5662               rFalseIfx.condition ^= 1;
5663               genSkipc(&rFalseIfx);
5664               if(ifx) ifx->generated = 1;
5665             }
5666
5667             return;
5668           }
5669
5670           if(lit & (0x80 << (size*8))) {
5671             /* Lit is less than zero */
5672             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
5673             //rFalseIfx.condition ^= 1;
5674             //genSkipCond(&rFalseIfx,left,size,7);
5675             //rFalseIfx.condition ^= 1;
5676             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5677             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5678
5679             if(rFalseIfx.condition)
5680               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5681             else
5682               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5683
5684
5685           } else {
5686             /* Lit is greater than or equal to zero */
5687             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5688             //rFalseIfx.condition ^= 1;
5689             //genSkipCond(&rFalseIfx,right,size,7);
5690             //rFalseIfx.condition ^= 1;
5691
5692             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5693             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5694
5695             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER));
5696             if(rFalseIfx.condition)
5697               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5698             else
5699               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5700
5701           }
5702
5703           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5704           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5705
5706           while(size--) {
5707
5708             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5709             emitSKPNZ;
5710             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5711           }
5712           rFalseIfx.condition ^= 1;
5713           //rFalseIfx.condition = 1;
5714           genSkipc(&rFalseIfx);
5715
5716           pic16_emitpLabel(truelbl->key);
5717
5718           if(ifx) ifx->generated = 1;
5719
5720
5721           if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5722             goto check_carry;
5723
5724           return;
5725           // end of if (sign)
5726         } else {
5727
5728           /* compare word or long to an unsigned literal on the right.*/
5729
5730
5731           size--;
5732           if(lit < 0xff) {
5733             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5734             switch (lit) {
5735             case 0:
5736               break; /* handled above */
5737 /*
5738             case 0xff:
5739               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5740               while(size--)
5741                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5742               genSkipz2(&rFalseIfx,0);
5743               break;
5744 */
5745             default:
5746               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5747               while(--size)
5748                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5749
5750               emitSKPZ;
5751               if(rFalseIfx.condition)
5752                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5753               else
5754                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5755
5756
5757               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5758               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5759
5760               rFalseIfx.condition ^= 1;
5761               genSkipc(&rFalseIfx);
5762             }
5763
5764             pic16_emitpLabel(truelbl->key);
5765
5766             if(ifx) ifx->generated = 1;
5767
5768             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5769               goto check_carry;
5770
5771             return;
5772           }
5773
5774
5775           lit++;
5776           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5777           i = (lit >> (size*8)) & 0xff;
5778
5779           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5780           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5781
5782           while(size--) {
5783             i = (lit >> (size*8)) & 0xff;
5784
5785             if(i) {
5786               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5787               emitSKPNZ;
5788               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5789             } else {
5790               /* this byte of the lit is zero, 
5791                * if it's not the last then OR in the variable */
5792               if(size)
5793                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5794             }
5795           }
5796
5797
5798           pic16_emitpLabel(lbl->key);
5799
5800           rFalseIfx.condition ^= 1;
5801
5802           genSkipc(&rFalseIfx);
5803         }
5804
5805         if(sign)
5806           pic16_emitpLabel(truelbl->key);
5807         if(ifx) ifx->generated = 1;
5808
5809             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5810               goto check_carry;
5811
5812         return;
5813       }
5814     }
5815     /* Compare two variables */
5816
5817     DEBUGpic16_emitcode(";sign","%d",sign);
5818
5819     size--;
5820     if(sign) {
5821       /* Sigh. thus sucks... */
5822       if(size) {
5823         pCodeOp *pctemp;
5824         
5825         pctemp = pic16_popGetTempReg(1);
5826         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5827         pic16_emitpcode(POC_MOVWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5828         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5829         pic16_emitpcode(POC_XORWF, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5830         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5831         pic16_emitpcode(POC_SUBFW, pctemp);             //pic16_popRegFromIdx(pic16_Gstack_base_addr));
5832         pic16_popReleaseTempReg(pctemp, 1);
5833       } else {
5834         /* Signed char comparison */
5835         /* Special thanks to Nikolai Golovchenko for this snippet */
5836         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5837         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5838         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5839         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5840         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5841         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5842
5843         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5844         genSkipc(&rFalseIfx);
5845           
5846         if(ifx) ifx->generated = 1;
5847
5848             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5849               goto check_carry;
5850
5851         return;
5852       }
5853
5854     } else {
5855
5856       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5857       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5858     }
5859
5860
5861     /* The rest of the bytes of a multi-byte compare */
5862     while (size) {
5863
5864       emitSKPZ;
5865       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5866       size--;
5867
5868       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5869       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5870
5871
5872     }
5873
5874     pic16_emitpLabel(lbl->key);
5875
5876     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5877     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5878         (AOP_TYPE(result) == AOP_REG)) {
5879       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5880       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5881     } else {
5882       genSkipc(&rFalseIfx);
5883     }         
5884     //genSkipc(&rFalseIfx);
5885     if(ifx) ifx->generated = 1;
5886
5887
5888             if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result)))
5889               goto check_carry;
5890
5891     return;
5892
5893   }
5894
5895 check_carry:
5896   if ((AOP_TYPE(result) != AOP_CRY) 
5897         && AOP_SIZE(result)) {
5898     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5899
5900     if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key );
5901
5902     pic16_outBitC(result);
5903   } else {
5904     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5905     /* if the result is used in the next
5906        ifx conditional branch then generate
5907        code a little differently */
5908     if (ifx )
5909       genIfxJump (ifx,"c");
5910     else
5911       pic16_outBitC(result);
5912     /* leave the result in acc */
5913   }
5914
5915 }
5916
5917 #elif 0 /* VR version of genCmp() */    /* } else { */
5918
5919 /* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */
5920 static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx,
5921         operand *result, int offset, int invert_op)
5922 {
5923   /* add code here */
5924   
5925   /* check condition, > or < ?? */
5926   if(rIfx->condition != 0)invert_op ^= 1;
5927   
5928   if(ifx && IC_FALSE(ifx))invert_op ^= 1;
5929
5930   if(!ifx)invert_op ^= 1;
5931
5932   DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d",
5933       __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op);
5934   
5935   /* do selection */
5936   if(!invert_op)return POC_CPFSGT;
5937   else return POC_CPFSLT;
5938 }
5939
5940 static int compareAopfirstpass=1;
5941
5942 static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl,
5943             operand *oper, int offset, operand *result,
5944             int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2,
5945             symbol *tlbl)
5946 {
5947   int op;
5948   symbol *truelbl;
5949
5950   /* invert if there is a result to be loaded, in order to fit,
5951    * SETC/CLRC sequence */
5952   if(AOP_SIZE(result))invert_op ^= 1;
5953
5954 //  if(sign && !offset)invert_op ^= 1;
5955   
5956 //  if(sign)invert_op ^= 1;
5957   
5958   op = selectCompareOp(resIfx, ifx, result, offset, invert_op);
5959
5960   if(AOP_SIZE(result) && compareAopfirstpass) {
5961     if(!ifx) {
5962       if(pcop2)
5963         pic16_emitpcode(POC_SETF, pcop2);
5964       else
5965         emitSETC;
5966     } else {
5967       if(pcop2)
5968         pic16_emitpcode(POC_CLRF, pcop2);
5969       else
5970         emitCLRC;
5971     }
5972   }
5973
5974   compareAopfirstpass = 0;
5975
5976       /* there is a bug when comparing operands with size > 1,
5977        * because higher bytes can be equal and test should be performed
5978        * to the next lower byte, current algorithm, considers operands
5979        * inequal in these cases! -- VR 20041107 */
5980
5981     
5982   if(pcop)
5983     pic16_emitpcode(op, pcop);
5984   else
5985     pic16_emitpcode(op, pic16_popGet(AOP(oper), offset));
5986
5987
5988   if((!sign || !offset) && AOP_SIZE(result)) {
5989     if(!ifx) {
5990       if(pcop2)
5991         pic16_emitpcode(POC_CLRF, pcop2);
5992         else
5993         emitCLRC;
5994     } else {
5995       if(pcop2)
5996         pic16_emitpcode(POC_SETF, pcop2);
5997       else
5998         emitSETC;
5999     }
6000     
6001     /* don't emit final branch (offset == 0) */
6002     if(offset) {
6003
6004       if(pcop2)
6005         pic16_emitpcode(POC_RRCF, pcop2);
6006
6007       pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key));
6008     }
6009   } else {
6010     if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) {
6011       DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d",
6012             __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset);
6013
6014       truelbl = newiTempLabel( NULL );
6015       pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key));
6016       if((!ifx || !IC_TRUE(ifx)) && (sign && !offset))
6017         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6018       else
6019         pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6020       pic16_emitpLabel(truelbl->key);
6021     } else {
6022       pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key));
6023     }
6024   }
6025 }
6026
6027 static void genCmp (operand *left, operand *right,
6028                     operand *result, iCode *ifx, int sign)
6029 {
6030   int size, cmpop=1;
6031   long lit = 0L;
6032   resolvedIfx rFalseIfx;
6033   symbol *falselbl, *tlbl;
6034
6035     FENTRY;
6036     
6037     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6038
6039     resolveIfx(&rFalseIfx, ifx);
6040     size = max(AOP_SIZE(left), AOP_SIZE(right));
6041     
6042     /* if left & right are bit variables */
6043     if(AOP_TYPE(left) == AOP_CRY
6044       && AOP_TYPE(right) == AOP_CRY ) {
6045
6046         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6047         pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
6048         
6049         werror(W_POSSBUG2, __FILE__, __LINE__);
6050         exit(EXIT_FAILURE);
6051     }
6052     
6053     /* if literal is on the right then swap with left */
6054     if((AOP_TYPE(right) == AOP_LIT)) {
6055       operand *tmp = right ;
6056 //      unsigned long mask = (0x100 << (8*(size-1))) - 1;
6057
6058         lit = /*(unsigned long)*/floatFromVal(AOP(right)->aopu.aop_lit);
6059
6060 //      lit = (lit - 1) & mask;
6061         right = left;
6062         left = tmp;
6063         rFalseIfx.condition ^= 1;               /* reverse compare */
6064     } else
6065     if ((AOP_TYPE(left) == AOP_LIT)) {
6066       /* float compares are handled by support functions */
6067       lit = /*(unsigned long)*/floatFromVal(AOP(left)->aopu.aop_lit);
6068     }
6069
6070     /* actual comparing algorithm */
6071 //    size = AOP_SIZE( right );
6072
6073     falselbl = newiTempLabel( NULL );
6074     if(AOP_TYPE(left) == AOP_LIT) {
6075       /* compare to literal */
6076       DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__);
6077       
6078       if(sign) {
6079         pCodeOp *pct, *pct2;
6080         symbol *tlbl1;
6081
6082         /* signed compare */
6083         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6084
6085         /* using PRODL:PRODH as a temporary register here */
6086         pct = pic16_popCopyReg(&pic16_pc_prodl);
6087         pct2 = pic16_popCopyReg(&pic16_pc_prodh);
6088         tlbl = newiTempLabel( NULL );
6089         
6090         /* first compare signs:
6091          *  a. if both are positive, compare just like unsigned
6092          *  b. if both are negative, invert cmpop, compare just like unsigned
6093          *  c. if different signs, determine the result directly */
6094
6095         size--;
6096
6097 #if 1
6098         /* { */
6099         tlbl1 = newiTempLabel( NULL );
6100 //        pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size));  /* move sign to carry */
6101
6102         if(lit > 0) {
6103
6104           /* literal is zero or positive:
6105            *  a. if carry is zero, too, continue compare,
6106            *  b. if carry is set, then continue depending on cmpop ^ condition:
6107            *    1. '<' return false (literal < variable),
6108            *    2. '>' return true (literal > variable) */
6109 //          pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key ));
6110           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6111           
6112           
6113           if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6114           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key ));
6115         } else 
6116         if(lit < 0) {
6117           
6118           /* literal is negative:
6119            *  a. if carry is set, too, continue compare,
6120            *  b. if carry is zero, then continue depending on cmpop ^ condition:
6121            *    1. '<' return true (literal < variable),
6122            *    2. '>' return false (literal > variable) */
6123 //          pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key ));
6124           pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6125           
6126           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6127           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6128         }
6129 #if 1
6130         else {
6131           /* lit == 0 */
6132           pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7));
6133           
6134           if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key ));
6135           else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key));
6136         }
6137 #endif
6138         
6139         
6140         pic16_emitpLabel( tlbl1->key );
6141 #endif  /* } */
6142
6143         compareAopfirstpass=1;
6144 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6145 //        pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6146 //        pic16_emitpcode(POC_MOVWF, pct);
6147
6148 //        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6149         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6150 //        compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6151         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6152
6153         /* generic case */        
6154           while( size-- ) {
6155 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
6156 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0));
6157 //            pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size));
6158 //            pic16_emitpcode(POC_MOVWF, pct);
6159
6160 //            pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80));
6161             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0));
6162             compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl);
6163 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6164 //            compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6165           }
6166         
6167         if(ifx)ifx->generated = 1;
6168
6169         if(AOP_SIZE(result)) {
6170           pic16_emitpLabel(tlbl->key);
6171           pic16_emitpLabel(falselbl->key);
6172           pic16_outBitOp( result, pct2 );
6173         } else {
6174           pic16_emitpLabel(tlbl->key);
6175         }
6176       } else {
6177
6178         /* unsigned compare */      
6179         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6180     
6181         compareAopfirstpass=1;
6182         while(size--) {
6183           
6184           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size)));
6185           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6186
6187         }
6188         if(ifx)ifx->generated = 1;
6189
6190         if(AOP_SIZE(result)) {
6191           pic16_emitpLabel(falselbl->key);
6192           pic16_outBitC( result );
6193         }
6194
6195       }
6196     } else {
6197       /* compare registers */
6198       DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__);
6199
6200
6201       if(sign) {
6202         pCodeOp *pct, *pct2;
6203         
6204         /* signed compare */
6205         DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__);
6206
6207         pct = pic16_popCopyReg(&pic16_pc_prodl);        /* first temporary register */
6208         pct2 = pic16_popCopyReg(&pic16_pc_prodh);       /* second temporary register */
6209         tlbl = newiTempLabel( NULL );
6210         
6211         compareAopfirstpass=1;
6212
6213         size--;
6214         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6215 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6216         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6217         pic16_emitpcode(POC_MOVWF, pct);
6218
6219         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6220 //        pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6221         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6222
6223         /* WREG already holds left + 0x80 */
6224         compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6225         
6226         while( size-- ) {
6227           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size));
6228 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6229           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6230           pic16_emitpcode(POC_MOVWF, pct);
6231                 
6232           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6233 //          pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
6234           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0));
6235
6236           /* WREG already holds left + 0x80 */
6237           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl);
6238 //          compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl);
6239         }
6240         
6241         if(ifx)ifx->generated = 1;
6242
6243         if(AOP_SIZE(result)) {
6244           pic16_emitpLabel(tlbl->key);
6245           pic16_emitpLabel(falselbl->key);
6246           pic16_outBitOp( result, pct2 );
6247         } else {
6248           pic16_emitpLabel(tlbl->key);
6249         }
6250
6251       } else {
6252         /* unsigned compare */      
6253         DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__);
6254
6255         compareAopfirstpass=1;
6256         while(size--) {
6257           
6258           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size));
6259           compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL);
6260
6261         }
6262
6263         if(ifx)ifx->generated = 1;
6264         if(AOP_SIZE(result)) {
6265
6266           pic16_emitpLabel(falselbl->key);
6267           pic16_outBitC( result );
6268         }
6269
6270       }
6271     }
6272 }
6273
6274 #endif  /* } */
6275
6276
6277
6278 /*-----------------------------------------------------------------*/
6279 /* genCmpGt :- greater than comparison                             */
6280 /*-----------------------------------------------------------------*/
6281 static void genCmpGt (iCode *ic, iCode *ifx)
6282 {
6283   operand *left, *right, *result;
6284   sym_link *letype , *retype;
6285   int sign ;
6286
6287     FENTRY;
6288     
6289     left = IC_LEFT(ic);
6290     right= IC_RIGHT(ic);
6291     result = IC_RESULT(ic);
6292
6293     letype = getSpec(operandType(left));
6294     retype =getSpec(operandType(right));
6295     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6296     /* assign the amsops */
6297     pic16_aopOp (left,ic,FALSE);
6298     pic16_aopOp (right,ic,FALSE);
6299     pic16_aopOp (result,ic,TRUE);
6300
6301     genCmp(right, left, result, ifx, sign);
6302
6303     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6304     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6305     pic16_freeAsmop(result,NULL,ic,TRUE); 
6306 }
6307
6308 /*-----------------------------------------------------------------*/
6309 /* genCmpLt - less than comparisons                                */
6310 /*-----------------------------------------------------------------*/
6311 static void genCmpLt (iCode *ic, iCode *ifx)
6312 {
6313   operand *left, *right, *result;
6314   sym_link *letype , *retype;
6315   int sign ;
6316
6317     FENTRY;
6318
6319     left = IC_LEFT(ic);
6320     right= IC_RIGHT(ic);
6321     result = IC_RESULT(ic);
6322
6323     letype = getSpec(operandType(left));
6324     retype =getSpec(operandType(right));
6325     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
6326
6327     /* assign the amsops */
6328     pic16_aopOp (left,ic,FALSE);
6329     pic16_aopOp (right,ic,FALSE);
6330     pic16_aopOp (result,ic,TRUE);
6331
6332     genCmp(left, right, result, ifx, sign);
6333
6334     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6335     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6336     pic16_freeAsmop(result,NULL,ic,TRUE); 
6337 }
6338
6339 #if 0
6340 // not needed ATM
6341 // FIXME reenable literal optimisation when the pic16 port is stable
6342
6343 /*-----------------------------------------------------------------*/
6344 /* genc16bit2lit - compare a 16 bit value to a literal             */
6345 /*-----------------------------------------------------------------*/
6346 static void genc16bit2lit(operand *op, int lit, int offset)
6347 {
6348   int i;
6349
6350   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
6351   if( (lit&0xff) == 0) 
6352     i=1;
6353   else
6354     i=0;
6355
6356   switch( BYTEofLONG(lit,i)) { 
6357   case 0:
6358     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6359     break;
6360   case 1:
6361     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6362     break;
6363   case 0xff:
6364     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6365     break;
6366   default:
6367     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
6368     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6369   }
6370
6371   i ^= 1;
6372
6373   switch( BYTEofLONG(lit,i)) { 
6374   case 0:
6375     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
6376     break;
6377   case 1:
6378     emitSKPNZ;
6379     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
6380     break;
6381   case 0xff:
6382     emitSKPNZ;
6383     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
6384     break;
6385   default:
6386     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
6387     emitSKPNZ;
6388     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
6389
6390   }
6391
6392 }
6393 #endif
6394
6395 #if 0
6396 // not needed ATM
6397 /*-----------------------------------------------------------------*/
6398 /* gencjneshort - compare and jump if not equal                    */
6399 /*-----------------------------------------------------------------*/
6400 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
6401 {
6402   int size = max(AOP_SIZE(left),AOP_SIZE(right));
6403   int offset = 0;
6404   int res_offset = 0;  /* the result may be a different size then left or right */
6405   int res_size = AOP_SIZE(result);
6406   resolvedIfx rIfx;
6407   symbol *lbl, *lbl_done;
6408
6409   unsigned long lit = 0L;
6410   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
6411
6412   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6413   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6414   if(result)
6415     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
6416   resolveIfx(&rIfx,ifx);
6417   lbl =  newiTempLabel(NULL);
6418   lbl_done =  newiTempLabel(NULL);
6419
6420
6421   /* if the left side is a literal or 
6422      if the right is in a pointer register and left 
6423      is not */
6424   if ((AOP_TYPE(left) == AOP_LIT) || 
6425       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6426     operand *t = right;
6427     right = left;
6428     left = t;
6429   }
6430   if(AOP_TYPE(right) == AOP_LIT)
6431     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6432
6433   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6434     preserve_result = 1;
6435
6436   if(result && !preserve_result)
6437     {
6438       int i;
6439       for(i = 0; i < AOP_SIZE(result); i++)
6440         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6441     }
6442
6443
6444   /* if the right side is a literal then anything goes */
6445   if (AOP_TYPE(right) == AOP_LIT &&
6446       AOP_TYPE(left) != AOP_DIR ) {
6447     switch(size) {
6448     case 2:
6449       genc16bit2lit(left, lit, 0);
6450       emitSKPZ;
6451       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6452       break;
6453     default:
6454       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6455       while (size--) {
6456         if(lit & 0xff) {
6457           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6458           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6459         } else {
6460           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6461         }
6462
6463         emitSKPZ;
6464         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6465         offset++;
6466         if(res_offset < res_size-1)
6467           res_offset++;
6468         lit >>= 8;
6469       }
6470       break;
6471     }
6472   }
6473
6474   /* if the right side is in a register or in direct space or
6475      if the left is a pointer register & right is not */    
6476   else if (AOP_TYPE(right) == AOP_REG ||
6477            AOP_TYPE(right) == AOP_DIR || 
6478            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
6479            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
6480     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
6481     int lbl_key = lbl->key;
6482
6483     if(result) {
6484       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
6485       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6486     }else {
6487       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6488       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
6489               __FUNCTION__,__LINE__);
6490       return;
6491     }
6492    
6493 /*     switch(size) { */
6494 /*     case 2: */
6495 /*       genc16bit2lit(left, lit, 0); */
6496 /*       emitSKPNZ; */
6497 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
6498 /*       break; */
6499 /*     default: */
6500     while (size--) {
6501       int emit_skip=1;
6502       if((AOP_TYPE(left) == AOP_DIR) && 
6503          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
6504
6505         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6506         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6507
6508       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
6509             
6510         switch (lit & 0xff) {
6511         case 0:
6512           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6513           break;
6514         case 1:
6515           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6516           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6517           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
6518           emit_skip=0;
6519           break;
6520         case 0xff:
6521           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6522           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6523           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6524           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6525           emit_skip=0;
6526           break;
6527         default:
6528           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6529           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6530         }
6531         lit >>= 8;
6532
6533       } else {
6534         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
6535       }
6536       if(emit_skip) {
6537         if(AOP_TYPE(result) == AOP_CRY) {
6538           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6539           if(rIfx.condition)
6540             emitSKPNZ;
6541           else
6542             emitSKPZ;
6543           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6544         } else {
6545           /* fix me. probably need to check result size too */
6546           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
6547           if(rIfx.condition)
6548             emitSKPZ;
6549           else
6550             emitSKPNZ;
6551           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
6552           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
6553         }
6554         if(ifx)
6555           ifx->generated=1;
6556       }
6557       emit_skip++;
6558       offset++;
6559       if(res_offset < res_size-1)
6560         res_offset++;
6561     }
6562 /*       break; */
6563 /*     } */
6564   } else if(AOP_TYPE(right) == AOP_REG &&
6565             AOP_TYPE(left) != AOP_DIR){
6566
6567     while(size--) {
6568       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6569       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6570       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
6571       if(rIfx.condition)
6572         emitSKPNZ;
6573       else
6574         emitSKPZ;
6575       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6576       offset++;
6577       if(res_offset < res_size-1)
6578         res_offset++;
6579     }
6580       
6581   }else{
6582     /* right is a pointer reg need both a & b */
6583     while(size--) {
6584       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
6585       if(strcmp(l,"b"))
6586         pic16_emitcode("mov","b,%s",l);
6587       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6588       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
6589       offset++;
6590     }
6591   }
6592
6593   if(result && preserve_result)
6594     {
6595       int i;
6596       for(i = 0; i < AOP_SIZE(result); i++)
6597         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6598     }
6599
6600   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
6601
6602   if(result && preserve_result)
6603     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
6604
6605   if(!rIfx.condition)
6606     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6607
6608   pic16_emitpLabel(lbl->key);
6609
6610   if(result && preserve_result)
6611     {
6612       int i;
6613       for(i = 0; i < AOP_SIZE(result); i++)
6614         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6615
6616       pic16_emitpLabel(lbl_done->key);
6617    }
6618
6619   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6620
6621   if(ifx)
6622     ifx->generated = 1;
6623 }
6624 #endif
6625
6626 #if 0
6627 /*-----------------------------------------------------------------*/
6628 /* gencjne - compare and jump if not equal                         */
6629 /*-----------------------------------------------------------------*/
6630 static void gencjne(operand *left, operand *right, iCode *ifx)
6631 {
6632     symbol *tlbl  = newiTempLabel(NULL);
6633
6634     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6635     gencjneshort(left, right, lbl);
6636
6637     pic16_emitcode("mov","a,%s",one);
6638     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
6639     pic16_emitcode("","%05d_DS_:",lbl->key+100);
6640     pic16_emitcode("clr","a");
6641     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6642
6643     pic16_emitpLabel(lbl->key);
6644     pic16_emitpLabel(tlbl->key);
6645
6646 }
6647 #endif
6648
6649
6650 /*-----------------------------------------------------------------*/
6651 /* is_LitOp - check if operand has to be treated as literal        */
6652 /*-----------------------------------------------------------------*/
6653 static bool is_LitOp(operand *op)
6654 {
6655   return ((AOP_TYPE(op) == AOP_LIT)
6656       || ( (AOP_TYPE(op) == AOP_PCODE)
6657           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
6658               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) )));
6659 }
6660
6661 /*-----------------------------------------------------------------*/
6662 /* is_LitAOp - check if operand has to be treated as literal        */
6663 /*-----------------------------------------------------------------*/
6664 static bool is_LitAOp(asmop *aop)
6665 {
6666   return ((aop->type == AOP_LIT)
6667       || ( (aop->type == AOP_PCODE)
6668           && ( (aop->aopu.pcop->type == PO_LITERAL)
6669               || (aop->aopu.pcop->type == PO_IMMEDIATE) )));
6670 }
6671
6672
6673
6674 /*-----------------------------------------------------------------*/
6675 /* genCmpEq - generates code for equal to                          */
6676 /*-----------------------------------------------------------------*/
6677 static void genCmpEq (iCode *ic, iCode *ifx)
6678 {
6679   operand *left, *right, *result;
6680   symbol *falselbl = newiTempLabel(NULL);
6681   symbol *donelbl = newiTempLabel(NULL);
6682
6683   int preserve_result = 0;
6684   int generate_result = 0;
6685   int i=0;
6686   unsigned long lit = -1;
6687
6688   FENTRY;
6689   
6690   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6691   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6692   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6693  
6694   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6695
6696   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
6697     {
6698       werror(W_POSSBUG2, __FILE__, __LINE__);
6699       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
6700       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
6701       goto release;
6702     }
6703
6704   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
6705     {
6706       operand *tmp = right ;
6707       right = left;
6708       left = tmp;
6709     }
6710
6711   if (AOP_TYPE(right) == AOP_LIT) {
6712     lit = (unsigned long) floatFromVal (AOP(right)->aopu.aop_lit);
6713   }
6714
6715   if ( regsInCommon(left, result) || regsInCommon(right, result) )
6716     preserve_result = 1;
6717
6718   if(result && AOP_SIZE(result))
6719     generate_result = 1;
6720
6721   if(generate_result && !preserve_result)
6722     {
6723       for(i = 0; i < AOP_SIZE(result); i++)
6724         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6725     }
6726
6727   assert( AOP_SIZE(left) == AOP_SIZE(right) );
6728   for(i=0; i < AOP_SIZE(left); i++)
6729     {
6730       if(AOP_TYPE(left) != AOP_ACC)
6731         {
6732           if(is_LitOp(left))
6733             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
6734           else
6735             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
6736         }
6737       if(is_LitOp(right)) {
6738         if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) {
6739           pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
6740         }
6741       } else
6742         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
6743
6744       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
6745     }
6746
6747   // result == true
6748
6749   if(generate_result && preserve_result)
6750     {
6751       for(i = 0; i < AOP_SIZE(result); i++)
6752         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6753     }
6754
6755   if(generate_result)
6756     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
6757
6758   if(generate_result && preserve_result)
6759     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6760
6761   if(ifx && IC_TRUE(ifx))
6762     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6763
6764   if(ifx && IC_FALSE(ifx))
6765     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
6766
6767   pic16_emitpLabel(falselbl->key);
6768
6769   // result == false
6770
6771   if(ifx && IC_FALSE(ifx))
6772     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6773
6774   if(generate_result && preserve_result)
6775     {
6776       for(i = 0; i < AOP_SIZE(result); i++)
6777         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
6778     }
6779
6780   pic16_emitpLabel(donelbl->key);
6781
6782   if(ifx)
6783     ifx->generated = 1;
6784
6785 release:
6786   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6787   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6788   pic16_freeAsmop(result,NULL,ic,TRUE);
6789
6790 }
6791
6792
6793 #if 0
6794 // old version kept for reference
6795
6796 /*-----------------------------------------------------------------*/
6797 /* genCmpEq - generates code for equal to                          */
6798 /*-----------------------------------------------------------------*/
6799 static void genCmpEq (iCode *ic, iCode *ifx)
6800 {
6801     operand *left, *right, *result;
6802     unsigned long lit = 0L;
6803     int size,offset=0;
6804     symbol *falselbl  = newiTempLabel(NULL);
6805
6806
6807     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6808
6809     if(ifx)
6810       DEBUGpic16_emitcode ("; ifx is non-null","");
6811     else
6812       DEBUGpic16_emitcode ("; ifx is null","");
6813
6814     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6815     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6816     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6817
6818     size = max(AOP_SIZE(left),AOP_SIZE(right));
6819
6820     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6821
6822     /* if literal, literal on the right or 
6823     if the right is in a pointer register and left 
6824     is not */
6825     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
6826         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
6827       operand *tmp = right ;
6828       right = left;
6829       left = tmp;
6830     }
6831
6832
6833     if(ifx && !AOP_SIZE(result)){
6834         symbol *tlbl;
6835         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
6836         /* if they are both bit variables */
6837         if (AOP_TYPE(left) == AOP_CRY &&
6838             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
6839                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
6840             if(AOP_TYPE(right) == AOP_LIT){
6841                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6842                 if(lit == 0L){
6843                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6844                     pic16_emitcode("cpl","c");
6845                 } else if(lit == 1L) {
6846                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6847                 } else {
6848                     pic16_emitcode("clr","c");
6849                 }
6850                 /* AOP_TYPE(right) == AOP_CRY */
6851             } else {
6852                 symbol *lbl = newiTempLabel(NULL);
6853                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6854                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
6855                 pic16_emitcode("cpl","c");
6856                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
6857             }
6858             /* if true label then we jump if condition
6859             supplied is true */
6860             tlbl = newiTempLabel(NULL);
6861             if ( IC_TRUE(ifx) ) {
6862                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
6863                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
6864             } else {
6865                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
6866                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
6867             }
6868             pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
6869
6870                 {
6871                 /* left and right are both bit variables, result is carry */
6872                         resolvedIfx rIfx;
6873               
6874                         resolveIfx(&rIfx,ifx);
6875
6876                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
6877                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
6878                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
6879                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
6880                         genSkipz2(&rIfx,0);
6881                 }
6882         } else {
6883
6884                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
6885
6886                         /* They're not both bit variables. Is the right a literal? */
6887                         if(AOP_TYPE(right) == AOP_LIT) {
6888                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
6889             
6890                         switch(size) {
6891
6892                                 case 1:
6893                                         switch(lit & 0xff) {
6894                                                 case 1:
6895                                                                 if ( IC_TRUE(ifx) ) {
6896                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
6897                                                                         emitSKPNZ;
6898                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6899                                                                 } else {
6900                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
6901                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6902                                                                 }
6903                                                                 break;
6904                                                 case 0xff:
6905                                                                 if ( IC_TRUE(ifx) ) {
6906                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
6907                                                                         emitSKPNZ;
6908                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6909                                                                 } else {
6910                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
6911                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6912                                                                 }
6913                                                                 break;
6914                                                 default:
6915                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6916                                                                 if(lit)
6917                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
6918                                                                 genSkip(ifx,'z');
6919                                         } // switch lit
6920
6921
6922                                         /* end of size == 1 */
6923                                         break;
6924               
6925                                 case 2:
6926                                         genc16bit2lit(left,lit,offset);
6927                                         genSkip(ifx,'z');
6928                                         break;
6929                                         /* end of size == 2 */
6930
6931                                 default:
6932                                         /* size is 4 */
6933                                         if(lit==0) {
6934                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6935                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
6936                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6937                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6938                                                 genSkip(ifx,'z');
6939                                         } else {
6940                                                 /* search for patterns that can be optimized */
6941
6942                                                 genc16bit2lit(left,lit,0);
6943                                                 lit >>= 16;
6944                                                 if(lit) {
6945                                                                 if(IC_TRUE(ifx))
6946                                                                 emitSKPZ; // if hi word unequal
6947                                                                 else
6948                                                                 emitSKPNZ; // if hi word equal
6949                                                                 // fail early
6950                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
6951                                                         genc16bit2lit(left,lit,2);
6952                                                         genSkip(ifx,'z');
6953                                                 } else {
6954                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
6955                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
6956                                                         genSkip(ifx,'z');
6957                                                 }
6958                                         }
6959                                                 pic16_emitpLabel(falselbl->key);
6960                                                 break;
6961
6962                         } // switch size
6963           
6964                         ifx->generated = 1;
6965                         goto release ;
6966             
6967
6968           } else if(AOP_TYPE(right) == AOP_CRY ) {
6969             /* we know the left is not a bit, but that the right is */
6970             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6971             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
6972                       pic16_popGet(AOP(right),offset));
6973             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
6974
6975             /* if the two are equal, then W will be 0 and the Z bit is set
6976              * we could test Z now, or go ahead and check the high order bytes if
6977              * the variable we're comparing is larger than a byte. */
6978
6979             while(--size)
6980               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
6981
6982             if ( IC_TRUE(ifx) ) {
6983               emitSKPNZ;
6984               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
6985               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
6986             } else {
6987               emitSKPZ;
6988               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
6989               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
6990             }
6991
6992           } else {
6993             /* They're both variables that are larger than bits */
6994             int s = size;
6995
6996             tlbl = newiTempLabel(NULL);
6997
6998             while(size--) {
6999               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7000               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7001
7002               if ( IC_TRUE(ifx) ) {
7003                 if(size) {
7004                   emitSKPZ;
7005                 
7006                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
7007
7008                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7009                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset);
7010                 } else {
7011                   emitSKPNZ;
7012
7013                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
7014
7015
7016                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
7017                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset);
7018                 }
7019               } else {
7020                 emitSKPZ;
7021
7022                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
7023
7024                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
7025                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset);
7026               }
7027               offset++;
7028             }
7029             if(s>1 && IC_TRUE(ifx)) {
7030               pic16_emitpLabel(tlbl->key);
7031               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset);                
7032             }
7033           }
7034         }
7035         /* mark the icode as generated */
7036         ifx->generated = 1;
7037         goto release ;
7038     }
7039
7040     /* if they are both bit variables */
7041     if (AOP_TYPE(left) == AOP_CRY &&
7042         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
7043         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
7044         if(AOP_TYPE(right) == AOP_LIT){
7045             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
7046             if(lit == 0L){
7047                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7048                 pic16_emitcode("cpl","c");
7049             } else if(lit == 1L) {
7050                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7051             } else {
7052                 pic16_emitcode("clr","c");
7053             }
7054             /* AOP_TYPE(right) == AOP_CRY */
7055         } else {
7056             symbol *lbl = newiTempLabel(NULL);
7057             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7058             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
7059             pic16_emitcode("cpl","c");
7060             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
7061         }
7062         /* c = 1 if egal */
7063         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
7064             pic16_outBitC(result);
7065             goto release ;
7066         }
7067         if (ifx) {
7068             genIfxJump (ifx,"c");
7069             goto release ;
7070         }
7071         /* if the result is used in an arithmetic operation
7072         then put the result in place */
7073         pic16_outBitC(result);
7074     } else {
7075       
7076       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
7077       gencjne(left,right,result,ifx);
7078 /*
7079       if(ifx) 
7080         gencjne(left,right,newiTempLabel(NULL));
7081       else {
7082         if(IC_TRUE(ifx)->key)
7083           gencjne(left,right,IC_TRUE(ifx)->key);
7084         else
7085           gencjne(left,right,IC_FALSE(ifx)->key);
7086         ifx->generated = 1;
7087         goto release ;
7088       }
7089       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
7090         pic16_aopPut(AOP(result),"a",0);
7091         goto release ;
7092       }
7093
7094       if (ifx) {
7095         genIfxJump (ifx,"a");
7096         goto release ;
7097       }
7098 */
7099       /* if the result is used in an arithmetic operation
7100          then put the result in place */
7101 /*
7102       if (AOP_TYPE(result) != AOP_CRY) 
7103         pic16_outAcc(result);
7104 */
7105       /* leave the result in acc */
7106     }
7107
7108 release:
7109     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7110     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7111     pic16_freeAsmop(result,NULL,ic,TRUE);
7112 }
7113 #endif
7114
7115 /*-----------------------------------------------------------------*/
7116 /* ifxForOp - returns the icode containing the ifx for operand     */
7117 /*-----------------------------------------------------------------*/
7118 static iCode *ifxForOp ( operand *op, iCode *ic )
7119 {
7120   FENTRY2;
7121
7122     /* if true symbol then needs to be assigned */
7123     if (IS_TRUE_SYMOP(op))
7124         return NULL ;
7125
7126     /* if this has register type condition and
7127     the next instruction is ifx with the same operand
7128     and live to of the operand is upto the ifx only then */
7129     if (ic->next
7130         && ic->next->op == IFX
7131         && IC_COND(ic->next)->key == op->key
7132         && OP_SYMBOL(op)->liveTo <= ic->next->seq
7133         ) {
7134                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
7135           return ic->next;
7136     }
7137
7138     /*
7139     if (ic->next &&
7140         ic->next->op == IFX &&
7141         IC_COND(ic->next)->key == op->key) {
7142       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7143       return ic->next;
7144     }
7145     */
7146
7147     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
7148     if (ic->next &&
7149         ic->next->op == IFX)
7150       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
7151
7152     if (ic->next &&
7153         ic->next->op == IFX &&
7154         IC_COND(ic->next)->key == op->key) {
7155       DEBUGpic16_emitcode ("; "," key is okay");
7156       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
7157                            OP_SYMBOL(op)->liveTo,
7158                            ic->next->seq);
7159     }
7160
7161 #if 0
7162     /* the code below is completely untested
7163      * it just allows ulong2fs.c compile -- VR */
7164          
7165     ic = ic->next;
7166     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
7167                                         __FILE__, __FUNCTION__, __LINE__);
7168         
7169     /* if this has register type condition and
7170     the next instruction is ifx with the same operand
7171     and live to of the operand is upto the ifx only then */
7172     if (ic->next &&
7173         ic->next->op == IFX &&
7174         IC_COND(ic->next)->key == op->key &&
7175         OP_SYMBOL(op)->liveTo <= ic->next->seq )
7176         return ic->next;
7177
7178     if (ic->next &&
7179         ic->next->op == IFX &&
7180         IC_COND(ic->next)->key == op->key) {
7181       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
7182       return ic->next;
7183     }
7184
7185     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
7186                                         __FILE__, __FUNCTION__, __LINE__);
7187
7188 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
7189 #endif
7190
7191     return NULL;
7192 }
7193 /*-----------------------------------------------------------------*/
7194 /* genAndOp - for && operation                                     */
7195 /*-----------------------------------------------------------------*/
7196 static void genAndOp (iCode *ic)
7197 {
7198   operand *left,*right, *result;
7199 /*     symbol *tlbl; */
7200
7201     FENTRY;
7202
7203     /* note here that && operations that are in an
7204     if statement are taken away by backPatchLabels
7205     only those used in arthmetic operations remain */
7206     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7207     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7208     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7209
7210     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7211
7212     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
7213     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
7214     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
7215
7216     /* if both are bit variables */
7217 /*     if (AOP_TYPE(left) == AOP_CRY && */
7218 /*         AOP_TYPE(right) == AOP_CRY ) { */
7219 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
7220 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
7221 /*         pic16_outBitC(result); */
7222 /*     } else { */
7223 /*         tlbl = newiTempLabel(NULL); */
7224 /*         pic16_toBoolean(left);     */
7225 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
7226 /*         pic16_toBoolean(right); */
7227 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
7228 /*         pic16_outBitAcc(result); */
7229 /*     } */
7230
7231     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7232     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7233     pic16_freeAsmop(result,NULL,ic,TRUE);
7234 }
7235
7236
7237 /*-----------------------------------------------------------------*/
7238 /* genOrOp - for || operation                                      */
7239 /*-----------------------------------------------------------------*/
7240 /*
7241   tsd pic port -
7242   modified this code, but it doesn't appear to ever get called
7243 */
7244
7245 static void genOrOp (iCode *ic)
7246 {
7247   operand *left,*right, *result;
7248   symbol *tlbl;
7249
7250     FENTRY;  
7251
7252   /* note here that || operations that are in an
7253     if statement are taken away by backPatchLabels
7254     only those used in arthmetic operations remain */
7255     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
7256     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
7257     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7258
7259     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7260
7261     /* if both are bit variables */
7262     if (AOP_TYPE(left) == AOP_CRY &&
7263         AOP_TYPE(right) == AOP_CRY ) {
7264       pic16_emitcode("clrc","");
7265       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7266                AOP(left)->aopu.aop_dir,
7267                AOP(left)->aopu.aop_dir);
7268       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7269                AOP(right)->aopu.aop_dir,
7270                AOP(right)->aopu.aop_dir);
7271       pic16_emitcode("setc","");
7272
7273     } else {
7274         tlbl = newiTempLabel(NULL);
7275         pic16_toBoolean(left);
7276         emitSKPZ;
7277         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset);
7278         pic16_toBoolean(right);
7279         pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset);
7280
7281         pic16_outBitAcc(result);
7282     }
7283
7284     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7285     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7286     pic16_freeAsmop(result,NULL,ic,TRUE);            
7287 }
7288
7289 /*-----------------------------------------------------------------*/
7290 /* isLiteralBit - test if lit == 2^n                               */
7291 /*-----------------------------------------------------------------*/
7292 static int isLiteralBit(unsigned long lit)
7293 {
7294     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
7295     0x100L,0x200L,0x400L,0x800L,
7296     0x1000L,0x2000L,0x4000L,0x8000L,
7297     0x10000L,0x20000L,0x40000L,0x80000L,
7298     0x100000L,0x200000L,0x400000L,0x800000L,
7299     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
7300     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
7301     int idx;
7302     
7303     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7304     for(idx = 0; idx < 32; idx++)
7305         if(lit == pw[idx])
7306             return idx+1;
7307     return 0;
7308 }
7309
7310 /*-----------------------------------------------------------------*/
7311 /* continueIfTrue -                                                */
7312 /*-----------------------------------------------------------------*/
7313 static void continueIfTrue (iCode *ic)
7314 {
7315   FENTRY;
7316   if(IC_TRUE(ic))
7317     pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7318   ic->generated = 1;
7319 }
7320
7321 /*-----------------------------------------------------------------*/
7322 /* jmpIfTrue -                                                     */
7323 /*-----------------------------------------------------------------*/
7324 static void jumpIfTrue (iCode *ic)
7325 {
7326   FENTRY;
7327   if(!IC_TRUE(ic))
7328     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7329   ic->generated = 1;
7330 }
7331
7332 /*-----------------------------------------------------------------*/
7333 /* jmpTrueOrFalse -                                                */
7334 /*-----------------------------------------------------------------*/
7335 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
7336 {
7337   // ugly but optimized by peephole
7338   FENTRY;
7339   if(IC_TRUE(ic)){
7340     symbol *nlbl = newiTempLabel(NULL);
7341       pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
7342       pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7343       pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
7344       pic16_emitcode("","%05d_DS_:",nlbl->key+100);
7345   } else {
7346     pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
7347     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7348   }
7349   ic->generated = 1;
7350 }
7351
7352 /*-----------------------------------------------------------------*/
7353 /* genAnd  - code for and                                          */
7354 /*-----------------------------------------------------------------*/
7355 static void genAnd (iCode *ic, iCode *ifx)
7356 {
7357   operand *left, *right, *result;
7358   int size, offset=0;  
7359   unsigned long lit = 0L;
7360   int bytelit = 0;
7361   resolvedIfx rIfx;
7362
7363     FENTRY;
7364     
7365   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7366   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7367   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7368
7369   resolveIfx(&rIfx,ifx);
7370
7371   /* if left is a literal & right is not then exchange them */
7372   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7373       AOP_NEEDSACC(left)) {
7374     operand *tmp = right ;
7375     right = left;
7376     left = tmp;
7377   }
7378
7379   /* if result = right then exchange them */
7380   if(pic16_sameRegs(AOP(result),AOP(right))){
7381     operand *tmp = right ;
7382     right = left;
7383     left = tmp;
7384   }
7385
7386   /* if right is bit then exchange them */
7387   if (AOP_TYPE(right) == AOP_CRY &&
7388       AOP_TYPE(left) != AOP_CRY){
7389     operand *tmp = right ;
7390     right = left;
7391     left = tmp;
7392   }
7393   if(AOP_TYPE(right) == AOP_LIT)
7394     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7395
7396   size = AOP_SIZE(result);
7397
7398   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7399
7400   // if(bit & yy)
7401   // result = bit & yy;
7402   if (AOP_TYPE(left) == AOP_CRY){
7403     // c = bit & literal;
7404     if(AOP_TYPE(right) == AOP_LIT){
7405       if(lit & 1) {
7406         if(size && pic16_sameRegs(AOP(result),AOP(left)))
7407           // no change
7408           goto release;
7409         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
7410       } else {
7411         // bit(result) = 0;
7412         if(size && (AOP_TYPE(result) == AOP_CRY)){
7413           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
7414           goto release;
7415         }
7416         if((AOP_TYPE(result) == AOP_CRY) && ifx){
7417           jumpIfTrue(ifx);
7418           goto release;
7419         }
7420         pic16_emitcode("clr","c");
7421       }
7422     } else {
7423       if (AOP_TYPE(right) == AOP_CRY){
7424         // c = bit & bit;
7425         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
7426         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7427       } else {
7428         // c = bit & val;
7429         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
7430         // c = lsb
7431         pic16_emitcode("rrc","a");
7432         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
7433       }
7434     }
7435     // bit = c
7436     // val = c
7437     if(size)
7438       pic16_outBitC(result);
7439     // if(bit & ...)
7440     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7441       genIfxJump(ifx, "c");           
7442     goto release ;
7443   }
7444
7445   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
7446   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
7447   if((AOP_TYPE(right) == AOP_LIT) &&
7448      (AOP_TYPE(result) == AOP_CRY) &&
7449      (AOP_TYPE(left) != AOP_CRY)){
7450     int posbit = isLiteralBit(lit);
7451     /* left &  2^n */
7452     if(posbit){
7453       posbit--;
7454       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
7455       // bit = left & 2^n
7456       if(size)
7457         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
7458       // if(left &  2^n)
7459       else{
7460         if(ifx){
7461 /*
7462           if(IC_TRUE(ifx)) {
7463             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7464             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
7465           } else {
7466             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7467             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
7468           }
7469 */
7470         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
7471         size = AOP_SIZE(left);
7472
7473         {
7474           int bp = posbit, ofs=0;
7475           
7476             while(bp > 7) {
7477               bp -= 8;
7478               ofs++;
7479             }
7480
7481           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7482                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER));
7483
7484         }
7485 /*
7486           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
7487                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
7488 */
7489           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
7490           
7491           ifx->generated = 1;
7492         }
7493         goto release;
7494       }
7495     } else {
7496       symbol *tlbl = newiTempLabel(NULL);
7497       int sizel = AOP_SIZE(left);
7498
7499       if(size)
7500         emitSETC;
7501
7502       while(sizel--) {
7503         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) {
7504
7505           /* patch provided by Aaron Colwell */
7506           if((posbit = isLiteralBit(bytelit)) != 0) {
7507               pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ),
7508                               pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE),
7509                                                 (posbit-1),0, PO_GPR_REGISTER));
7510
7511               pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key));
7512 //              pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7513           } else {
7514               if (bytelit == 0xff) {
7515                   /* Aaron had a MOVF instruction here, changed to MOVFW cause
7516                    * a peephole could optimize it out -- VR */
7517                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7518               } else {
7519                   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset));
7520                   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit));
7521               }
7522
7523               pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ),
7524                             pic16_popGetLabel(tlbl->key));
7525           }
7526         
7527 #if 0
7528           /* old code, left here for reference -- VR 09/2004 */
7529           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7530           // byte ==  2^n ?
7531           if((posbit = isLiteralBit(bytelit)) != 0)
7532             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
7533           else{
7534             if(bytelit != 0x0FFL)
7535               pic16_emitcode("anl","a,%s",
7536                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
7537             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7538           }
7539 #endif
7540         }
7541         offset++;
7542       }
7543       // bit = left & literal
7544       if(size) {
7545         emitCLRC;
7546         pic16_emitpLabel(tlbl->key);
7547       }
7548       // if(left & literal)
7549       else {
7550         if(ifx) {
7551           pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key));
7552           ifx->generated = 1;
7553         }
7554         pic16_emitpLabel(tlbl->key);
7555         goto release;
7556       }
7557     }
7558
7559     pic16_outBitC(result);
7560     goto release ;
7561   }
7562
7563   /* if left is same as result */
7564   if(pic16_sameRegs(AOP(result),AOP(left))){
7565     int know_W = -1;
7566     for(;size--; offset++,lit>>=8) {
7567       if(AOP_TYPE(right) == AOP_LIT){
7568         switch(lit & 0xff) {
7569         case 0x00:
7570           /*  and'ing with 0 has clears the result */
7571 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7572           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7573           break;
7574         case 0xff:
7575           /* and'ing with 0xff is a nop when the result and left are the same */
7576           break;
7577
7578         default:
7579           {
7580             int p = pic16_my_powof2( (~lit) & 0xff );
7581             if(p>=0) {
7582               /* only one bit is set in the literal, so use a bcf instruction */
7583 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
7584               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7585
7586             } else {
7587               pic16_emitcode("movlw","0x%x", (lit & 0xff));
7588               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7589               if(know_W != (lit&0xff))
7590                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7591               know_W = lit &0xff;
7592               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7593             }
7594           }    
7595         }
7596       } else {
7597         if (AOP_TYPE(left) == AOP_ACC) {
7598           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7599         } else {                    
7600           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7601           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
7602
7603         }
7604       }
7605     }
7606
7607   } else {
7608     // left & result in different registers
7609     if(AOP_TYPE(result) == AOP_CRY){
7610       // result = bit
7611       // if(size), result in bit
7612       // if(!size && ifx), conditional oper: if(left & right)
7613       symbol *tlbl = newiTempLabel(NULL);
7614       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
7615       if(size)
7616         pic16_emitcode("setb","c");
7617       while(sizer--){
7618         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7619         pic16_emitcode("anl","a,%s",
7620                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7621         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7622         offset++;
7623       }
7624       if(size){
7625         CLRC;
7626         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7627         pic16_outBitC(result);
7628       } else if(ifx)
7629         jmpTrueOrFalse(ifx, tlbl);
7630     } else {
7631       for(;(size--);offset++) {
7632         // normal case
7633         // result = left & right
7634         if(AOP_TYPE(right) == AOP_LIT){
7635           int t = (lit >> (offset*8)) & 0x0FFL;
7636           switch(t) { 
7637           case 0x00:
7638             pic16_emitcode("clrf","%s",
7639                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7640             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
7641             break;
7642           case 0xff:
7643             pic16_emitcode("movf","%s,w",
7644                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7645             pic16_emitcode("movwf","%s",
7646                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7647             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7648             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7649             break;
7650           default:
7651             pic16_emitcode("movlw","0x%x",t);
7652             pic16_emitcode("andwf","%s,w",
7653                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7654             pic16_emitcode("movwf","%s",
7655                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7656               
7657             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7658             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7659             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7660           }
7661           continue;
7662         }
7663
7664         if (AOP_TYPE(left) == AOP_ACC) {
7665           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7666           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
7667         } else {
7668           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7669           pic16_emitcode("andwf","%s,w",
7670                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7671           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7672           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
7673         }
7674         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7675         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7676       }
7677     }
7678   }
7679
7680   release :
7681     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7682   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7683   pic16_freeAsmop(result,NULL,ic,TRUE);     
7684 }
7685
7686 /*-----------------------------------------------------------------*/
7687 /* genOr  - code for or                                            */
7688 /*-----------------------------------------------------------------*/
7689 static void genOr (iCode *ic, iCode *ifx)
7690 {
7691     operand *left, *right, *result;
7692     int size, offset=0;
7693     unsigned long lit = 0L;
7694
7695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7696
7697     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
7698     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
7699     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
7700
7701     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7702
7703     /* if left is a literal & right is not then exchange them */
7704     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
7705         AOP_NEEDSACC(left)) {
7706         operand *tmp = right ;
7707         right = left;
7708         left = tmp;
7709     }
7710
7711     /* if result = right then exchange them */
7712     if(pic16_sameRegs(AOP(result),AOP(right))){
7713         operand *tmp = right ;
7714         right = left;
7715         left = tmp;
7716     }
7717
7718     /* if right is bit then exchange them */
7719     if (AOP_TYPE(right) == AOP_CRY &&
7720         AOP_TYPE(left) != AOP_CRY){
7721         operand *tmp = right ;
7722         right = left;
7723         left = tmp;
7724     }
7725
7726     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
7727
7728     if(AOP_TYPE(right) == AOP_LIT)
7729         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
7730
7731     size = AOP_SIZE(result);
7732
7733     // if(bit | yy)
7734     // xx = bit | yy;
7735     if (AOP_TYPE(left) == AOP_CRY){
7736         if(AOP_TYPE(right) == AOP_LIT){
7737             // c = bit & literal;
7738             if(lit){
7739                 // lit != 0 => result = 1
7740                 if(AOP_TYPE(result) == AOP_CRY){
7741                   if(size)
7742                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
7743                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7744                   //     AOP(result)->aopu.aop_dir,
7745                   //     AOP(result)->aopu.aop_dir);
7746                     else if(ifx)
7747                         continueIfTrue(ifx);
7748                     goto release;
7749                 }
7750             } else {
7751                 // lit == 0 => result = left
7752                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
7753                     goto release;
7754                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
7755             }
7756         } else {
7757             if (AOP_TYPE(right) == AOP_CRY){
7758               if(pic16_sameRegs(AOP(result),AOP(left))){
7759                 // c = bit | bit;
7760                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7761                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
7762                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7763
7764                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7765                          AOP(result)->aopu.aop_dir,
7766                          AOP(result)->aopu.aop_dir);
7767                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7768                          AOP(right)->aopu.aop_dir,
7769                          AOP(right)->aopu.aop_dir);
7770                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7771                          AOP(result)->aopu.aop_dir,
7772                          AOP(result)->aopu.aop_dir);
7773               } else {
7774                 if( AOP_TYPE(result) == AOP_ACC) {
7775                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7776                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7777                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7778                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
7779
7780                 } else {
7781
7782                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7783                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
7784                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7785                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7786
7787                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
7788                                  AOP(result)->aopu.aop_dir,
7789                                  AOP(result)->aopu.aop_dir);
7790                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
7791                                  AOP(right)->aopu.aop_dir,
7792                                  AOP(right)->aopu.aop_dir);
7793                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
7794                                  AOP(left)->aopu.aop_dir,
7795                                  AOP(left)->aopu.aop_dir);
7796                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
7797                                  AOP(result)->aopu.aop_dir,
7798                                  AOP(result)->aopu.aop_dir);
7799                 }
7800               }
7801             } else {
7802                 // c = bit | val;
7803                 symbol *tlbl = newiTempLabel(NULL);
7804                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7805
7806
7807                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
7808                 if( AOP_TYPE(right) == AOP_ACC) {
7809                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
7810                   emitSKPNZ;
7811                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
7812                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
7813                 }
7814
7815
7816
7817                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
7818                     pic16_emitcode(";XXX setb","c");
7819                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
7820                          AOP(left)->aopu.aop_dir,tlbl->key+100);
7821                 pic16_toBoolean(right);
7822                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7823                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
7824                     jmpTrueOrFalse(ifx, tlbl);
7825                     goto release;
7826                 } else {
7827                     CLRC;
7828                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7829                 }
7830             }
7831         }
7832         // bit = c
7833         // val = c
7834         if(size)
7835             pic16_outBitC(result);
7836         // if(bit | ...)
7837         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
7838             genIfxJump(ifx, "c");           
7839         goto release ;
7840     }
7841
7842     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
7843     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
7844     if((AOP_TYPE(right) == AOP_LIT) &&
7845        (AOP_TYPE(result) == AOP_CRY) &&
7846        (AOP_TYPE(left) != AOP_CRY)){
7847         if(lit){
7848           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7849             // result = 1
7850             if(size)
7851                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
7852             else 
7853                 continueIfTrue(ifx);
7854             goto release;
7855         } else {
7856           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7857             // lit = 0, result = boolean(left)
7858             if(size)
7859                 pic16_emitcode(";XXX setb","c");
7860             pic16_toBoolean(right);
7861             if(size){
7862                 symbol *tlbl = newiTempLabel(NULL);
7863                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7864                 CLRC;
7865                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7866             } else {
7867                 genIfxJump (ifx,"a");
7868                 goto release;
7869             }
7870         }
7871         pic16_outBitC(result);
7872         goto release ;
7873     }
7874
7875     /* if left is same as result */
7876     if(pic16_sameRegs(AOP(result),AOP(left))){
7877       int know_W = -1;
7878       for(;size--; offset++,lit>>=8) {
7879         if(AOP_TYPE(right) == AOP_LIT){
7880           if((lit & 0xff) == 0)
7881             /*  or'ing with 0 has no effect */
7882             continue;
7883           else {
7884             int p = pic16_my_powof2(lit & 0xff);
7885             if(p>=0) {
7886               /* only one bit is set in the literal, so use a bsf instruction */
7887               pic16_emitpcode(POC_BSF,
7888                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER));
7889             } else {
7890               if(know_W != (lit & 0xff))
7891                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
7892               know_W = lit & 0xff;
7893               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
7894             }
7895                     
7896           }
7897         } else {
7898           if (AOP_TYPE(left) == AOP_ACC) {
7899             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
7900 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7901           } else {                  
7902             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7903             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
7904
7905 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7906 //          pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7907
7908           }
7909         }
7910       }
7911     } else {
7912         // left & result in different registers
7913         if(AOP_TYPE(result) == AOP_CRY){
7914             // result = bit
7915             // if(size), result in bit
7916             // if(!size && ifx), conditional oper: if(left | right)
7917             symbol *tlbl = newiTempLabel(NULL);
7918             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7919             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
7920
7921
7922             if(size)
7923                 pic16_emitcode(";XXX setb","c");
7924             while(sizer--){
7925                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7926                 pic16_emitcode(";XXX orl","a,%s",
7927                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7928                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
7929                 offset++;
7930             }
7931             if(size){
7932                 CLRC;
7933                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7934                 pic16_outBitC(result);
7935             } else if(ifx)
7936                 jmpTrueOrFalse(ifx, tlbl);
7937         } else for(;(size--);offset++){
7938           // normal case
7939           // result = left & right
7940           if(AOP_TYPE(right) == AOP_LIT){
7941             int t = (lit >> (offset*8)) & 0x0FFL;
7942             switch(t) { 
7943             case 0x00:
7944               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7945               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7946
7947 //            pic16_emitcode("movf","%s,w",
7948 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7949 //            pic16_emitcode("movwf","%s",
7950 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7951               break;
7952             default:
7953               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
7954               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7955               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7956
7957 //            pic16_emitcode("movlw","0x%x",t);
7958 //            pic16_emitcode("iorwf","%s,w",
7959 //                     pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7960 //            pic16_emitcode("movwf","%s",
7961 //                     pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7962               
7963             }
7964             continue;
7965           }
7966
7967           // faster than result <- left, anl result,right
7968           // and better if result is SFR
7969           if (AOP_TYPE(left) == AOP_ACC) {
7970             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
7971 //          pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7972           } else {
7973             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
7974             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
7975
7976 //          pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7977 //          pic16_emitcode("iorwf","%s,w",
7978 //                   pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7979           }
7980           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7981 //        pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7982         }
7983     }
7984
7985 release :
7986     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7987     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7988     pic16_freeAsmop(result,NULL,ic,TRUE);     
7989 }
7990
7991 /*-----------------------------------------------------------------*/
7992 /* genXor - code for xclusive or                                   */
7993 /*-----------------------------------------------------------------*/
7994 static void genXor (iCode *ic, iCode *ifx)
7995 {
7996   operand *left, *right, *result;
7997   int size, offset=0;
7998   unsigned long lit = 0L;
7999
8000   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8001
8002   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
8003   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
8004   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
8005
8006   /* if left is a literal & right is not ||
8007      if left needs acc & right does not */
8008   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
8009       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
8010     operand *tmp = right ;
8011     right = left;
8012     left = tmp;
8013   }
8014
8015   /* if result = right then exchange them */
8016   if(pic16_sameRegs(AOP(result),AOP(right))){
8017     operand *tmp = right ;
8018     right = left;
8019     left = tmp;
8020   }
8021
8022   /* if right is bit then exchange them */
8023   if (AOP_TYPE(right) == AOP_CRY &&
8024       AOP_TYPE(left) != AOP_CRY){
8025     operand *tmp = right ;
8026     right = left;
8027     left = tmp;
8028   }
8029   if(AOP_TYPE(right) == AOP_LIT)
8030     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
8031
8032   size = AOP_SIZE(result);
8033
8034   // if(bit ^ yy)
8035   // xx = bit ^ yy;
8036   if (AOP_TYPE(left) == AOP_CRY){
8037     if(AOP_TYPE(right) == AOP_LIT){
8038       // c = bit & literal;
8039       if(lit>>1){
8040         // lit>>1  != 0 => result = 1
8041         if(AOP_TYPE(result) == AOP_CRY){
8042           if(size)
8043             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
8044             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
8045           else if(ifx)
8046             continueIfTrue(ifx);
8047           goto release;
8048         }
8049         pic16_emitcode("setb","c");
8050       } else{
8051         // lit == (0 or 1)
8052         if(lit == 0){
8053           // lit == 0, result = left
8054           if(size && pic16_sameRegs(AOP(result),AOP(left)))
8055             goto release;
8056           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8057         } else{
8058           // lit == 1, result = not(left)
8059           if(size && pic16_sameRegs(AOP(result),AOP(left))){
8060             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
8061             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
8062             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
8063             goto release;
8064           } else {
8065             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
8066             pic16_emitcode("cpl","c");
8067           }
8068         }
8069       }
8070
8071     } else {
8072       // right != literal
8073       symbol *tlbl = newiTempLabel(NULL);
8074       if (AOP_TYPE(right) == AOP_CRY){
8075         // c = bit ^ bit;
8076         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
8077       }
8078       else{
8079         int sizer = AOP_SIZE(right);
8080         // c = bit ^ val
8081         // if val>>1 != 0, result = 1
8082         pic16_emitcode("setb","c");
8083         while(sizer){
8084           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
8085           if(sizer == 1)
8086             // test the msb of the lsb
8087             pic16_emitcode("anl","a,#0xfe");
8088           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8089           sizer--;
8090         }
8091         // val = (0,1)
8092         pic16_emitcode("rrc","a");
8093       }
8094       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
8095       pic16_emitcode("cpl","c");
8096       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
8097     }
8098     // bit = c
8099     // val = c
8100     if(size)
8101       pic16_outBitC(result);
8102     // if(bit | ...)
8103     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
8104       genIfxJump(ifx, "c");           
8105     goto release ;
8106   }
8107
8108   if(pic16_sameRegs(AOP(result),AOP(left))){
8109     /* if left is same as result */
8110     for(;size--; offset++) {
8111       if(AOP_TYPE(right) == AOP_LIT){
8112         int t  = (lit >> (offset*8)) & 0x0FFL;
8113         if(t == 0x00L)
8114           continue;
8115         else
8116           if (IS_AOP_PREG(left)) {
8117             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8118             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8119             pic16_aopPut(AOP(result),"a",offset);
8120           } else {
8121             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8122             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8123             pic16_emitcode("xrl","%s,%s",
8124                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
8125                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8126           }
8127       } else {
8128         if (AOP_TYPE(left) == AOP_ACC)
8129           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8130         else {
8131           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8132           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
8133 /*
8134           if (IS_AOP_PREG(left)) {
8135             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8136             pic16_aopPut(AOP(result),"a",offset);
8137           } else
8138             pic16_emitcode("xrl","%s,a",
8139                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
8140 */
8141         }
8142       }
8143     }
8144   } else {
8145     // left & result in different registers
8146     if(AOP_TYPE(result) == AOP_CRY){
8147       // result = bit
8148       // if(size), result in bit
8149       // if(!size && ifx), conditional oper: if(left ^ right)
8150       symbol *tlbl = newiTempLabel(NULL);
8151       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
8152       if(size)
8153         pic16_emitcode("setb","c");
8154       while(sizer--){
8155         if((AOP_TYPE(right) == AOP_LIT) &&
8156            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
8157           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8158         } else {
8159           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8160           pic16_emitcode("xrl","a,%s",
8161                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8162         }
8163         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
8164         offset++;
8165       }
8166       if(size){
8167         CLRC;
8168         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8169         pic16_outBitC(result);
8170       } else if(ifx)
8171         jmpTrueOrFalse(ifx, tlbl);
8172     } else for(;(size--);offset++){
8173       // normal case
8174       // result = left & right
8175       if(AOP_TYPE(right) == AOP_LIT){
8176         int t = (lit >> (offset*8)) & 0x0FFL;
8177         switch(t) { 
8178         case 0x00:
8179           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
8180           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8181           pic16_emitcode("movf","%s,w",
8182                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8183           pic16_emitcode("movwf","%s",
8184                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8185           break;
8186         case 0xff:
8187           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
8188           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8189           pic16_emitcode("comf","%s,w",
8190                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8191           pic16_emitcode("movwf","%s",
8192                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8193           break;
8194         default:
8195           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
8196           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8197           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8198           pic16_emitcode("movlw","0x%x",t);
8199           pic16_emitcode("xorwf","%s,w",
8200                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8201           pic16_emitcode("movwf","%s",
8202                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8203
8204         }
8205         continue;
8206       }
8207
8208       // faster than result <- left, anl result,right
8209       // and better if result is SFR
8210       if (AOP_TYPE(left) == AOP_ACC) {
8211         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
8212         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8213       } else {
8214         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
8215         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
8216         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
8217         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8218       }
8219       if ( AOP_TYPE(result) != AOP_ACC){
8220         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
8221         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
8222       }
8223     }
8224   }
8225
8226   release :
8227     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8228   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
8229   pic16_freeAsmop(result,NULL,ic,TRUE);     
8230 }
8231
8232 /*-----------------------------------------------------------------*/
8233 /* genInline - write the inline code out                           */
8234 /*-----------------------------------------------------------------*/
8235 static void genInline (iCode *ic)
8236 {
8237   char *buffer, *bp, *bp1;
8238     
8239         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8240
8241         _G.inLine += (!options.asmpeep);
8242
8243         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
8244         strcpy(buffer,IC_INLINE(ic));
8245         
8246         while((bp1=strstr(bp, "\\n"))) {
8247           *bp1++ = '\n';
8248           *bp1++ = ' ';
8249           bp = bp1;
8250         }
8251         bp = bp1 = buffer;
8252
8253 #if 0
8254   /* This is an experimental code for #pragma inline
8255      and is temporarily disabled for 2.5.0 release */
8256         if(asmInlineMap)
8257         {
8258           symbol *sym;
8259           char *s;
8260           char *cbuf;
8261           int cblen;
8262
8263             cbuf = Safe_strdup(buffer);
8264             cblen = strlen(buffer)+1;
8265             memset(cbuf, 0, cblen);
8266
8267             bp = buffer;
8268             bp1 = cbuf;
8269             while(*bp) {
8270               if(*bp != '%')*bp1++ = *bp++;
8271               else {
8272                 int i;
8273
8274                   bp++;
8275                   i = *bp - '0';
8276                   if(i>elementsInSet(asmInlineMap))break;
8277                   
8278                   bp++;
8279                   s = indexSet(asmInlineMap, i);
8280                   DEBUGpc("searching symbol s = `%s'", s);
8281                   sym = findSym(SymbolTab, NULL, s);
8282
8283                   if(sym->reqv) {
8284                     strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name);
8285                   } else {
8286                     strcat(bp1, sym->rname);
8287                   }
8288                   
8289                   while(*bp1)bp1++;
8290               }
8291               
8292               if(strlen(bp1) > cblen - 16) {
8293                 int i = strlen(cbuf);
8294                 cblen += 50;
8295                 cbuf = realloc(cbuf, cblen);
8296                 memset(cbuf+i, 0, 50);
8297                 bp1 = cbuf + i;
8298               }
8299             }
8300             
8301             free(buffer);
8302             buffer = Safe_strdup( cbuf );
8303             free(cbuf);
8304             
8305             bp = bp1 = buffer;
8306         }
8307 #endif  /* 0 */
8308
8309         /* emit each line as a code */
8310         while (*bp) {
8311                 if (*bp == '\n') {
8312                         *bp++ = '\0';
8313
8314                         if(*bp1)
8315                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8316                         bp1 = bp;
8317                 } else {
8318                         if (*bp == ':') {
8319                                 bp++;
8320                                 *bp = '\0';
8321                                 bp++;
8322
8323                                 /* print label, use this special format with NULL directive
8324                                  * to denote that the argument should not be indented with tab */
8325                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
8326                                 bp1 = bp;
8327                         } if (*bp == ';') {
8328                                 /* advance to end of line (prevent splitting of comments at ':' */
8329                                 while (*bp && *bp != '\n') {
8330                                         bp++;
8331                                 } // while
8332                         } else
8333                                 bp++;
8334                 }
8335         }
8336
8337         if ((bp1 != bp) && *bp1)
8338                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
8339
8340
8341     Safe_free(buffer);
8342
8343     _G.inLine -= (!options.asmpeep);
8344 }
8345
8346 /*-----------------------------------------------------------------*/
8347 /* genRRC - rotate right with carry                                */
8348 /*-----------------------------------------------------------------*/
8349 static void genRRC (iCode *ic)
8350 {
8351   operand *left , *result ;
8352   int size, offset = 0, same;
8353
8354   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8355
8356   /* rotate right with carry */
8357   left = IC_LEFT(ic);
8358   result=IC_RESULT(ic);
8359   pic16_aopOp (left,ic,FALSE);
8360   pic16_aopOp (result,ic,TRUE);
8361
8362   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8363
8364   same = pic16_sameRegs(AOP(result),AOP(left));
8365
8366   size = AOP_SIZE(result);    
8367
8368   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
8369
8370   /* get the lsb and put it into the carry */
8371   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
8372
8373   offset = 0 ;
8374
8375   while(size--) {
8376
8377     if(same) {
8378       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
8379     } else {
8380       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
8381       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8382     }
8383
8384     offset++;
8385   }
8386
8387   pic16_freeAsmop(left,NULL,ic,TRUE);
8388   pic16_freeAsmop(result,NULL,ic,TRUE);
8389 }
8390
8391 /*-----------------------------------------------------------------*/
8392 /* genRLC - generate code for rotate left with carry               */
8393 /*-----------------------------------------------------------------*/
8394 static void genRLC (iCode *ic)
8395 {    
8396   operand *left , *result ;
8397   int size, offset = 0;
8398   int same;
8399
8400   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8401   /* rotate right with carry */
8402   left = IC_LEFT(ic);
8403   result=IC_RESULT(ic);
8404   pic16_aopOp (left,ic,FALSE);
8405   pic16_aopOp (result,ic,TRUE);
8406
8407   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8408
8409   same = pic16_sameRegs(AOP(result),AOP(left));
8410
8411   /* move it to the result */
8412   size = AOP_SIZE(result);    
8413
8414   /* get the msb and put it into the carry */
8415   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
8416
8417   offset = 0 ;
8418
8419   while(size--) {
8420
8421     if(same) {
8422       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
8423     } else {
8424       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
8425       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8426     }
8427
8428     offset++;
8429   }
8430
8431
8432   pic16_freeAsmop(left,NULL,ic,TRUE);
8433   pic16_freeAsmop(result,NULL,ic,TRUE);
8434 }
8435
8436
8437 /* gpasm can get the highest order bit with HIGH/UPPER
8438  * so the following probably is not needed -- VR */
8439  
8440 /*-----------------------------------------------------------------*/
8441 /* genGetHbit - generates code get highest order bit               */
8442 /*-----------------------------------------------------------------*/
8443 static void genGetHbit (iCode *ic)
8444 {
8445     operand *left, *result;
8446     left = IC_LEFT(ic);
8447     result=IC_RESULT(ic);
8448     pic16_aopOp (left,ic,FALSE);
8449     pic16_aopOp (result,ic,FALSE);
8450
8451     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8452     /* get the highest order byte into a */
8453     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
8454     if(AOP_TYPE(result) == AOP_CRY){
8455         pic16_emitcode("rlc","a");
8456         pic16_outBitC(result);
8457     }
8458     else{
8459         pic16_emitcode("rl","a");
8460         pic16_emitcode("anl","a,#0x01");
8461         pic16_outAcc(result);
8462     }
8463
8464
8465     pic16_freeAsmop(left,NULL,ic,TRUE);
8466     pic16_freeAsmop(result,NULL,ic,TRUE);
8467 }
8468
8469 #if 0
8470 /*-----------------------------------------------------------------*/
8471 /* AccRol - rotate left accumulator by known count                 */
8472 /*-----------------------------------------------------------------*/
8473 static void AccRol (int shCount)
8474 {
8475     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8476     shCount &= 0x0007;              // shCount : 0..7
8477     switch(shCount){
8478         case 0 :
8479             break;
8480         case 1 :
8481             pic16_emitcode("rl","a");
8482             break;
8483         case 2 :
8484             pic16_emitcode("rl","a");
8485             pic16_emitcode("rl","a");
8486             break;
8487         case 3 :
8488             pic16_emitcode("swap","a");
8489             pic16_emitcode("rr","a");
8490             break;
8491         case 4 :
8492             pic16_emitcode("swap","a");
8493             break;
8494         case 5 :
8495             pic16_emitcode("swap","a");
8496             pic16_emitcode("rl","a");
8497             break;
8498         case 6 :
8499             pic16_emitcode("rr","a");
8500             pic16_emitcode("rr","a");
8501             break;
8502         case 7 :
8503             pic16_emitcode("rr","a");
8504             break;
8505     }
8506 }
8507 #endif
8508
8509 /*-----------------------------------------------------------------*/
8510 /* AccLsh - left shift accumulator by known count                  */
8511 /*-----------------------------------------------------------------*/
8512 static void AccLsh (int shCount, int doMask)
8513 {
8514         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8515         switch(shCount){
8516                 case 0 :
8517                         return;
8518                         break;
8519                 case 1 :
8520                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8521                         break;
8522                 case 2 :
8523                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8524                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8525                         break;
8526                 case 3 :
8527                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8528                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8529                         break;
8530                 case 4 :
8531                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8532                         break;
8533                 case 5 :
8534                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8535                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8536                         break;
8537                 case 6 :
8538                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8539                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8540                         break;
8541                 case 7 :
8542                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8543                         break;
8544         }
8545         if (doMask) {
8546                 /* no masking is required in genPackBits */
8547                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
8548         }
8549 }
8550
8551 /*-----------------------------------------------------------------*/
8552 /* AccRsh - right shift accumulator by known count                 */
8553 /*-----------------------------------------------------------------*/
8554 static void AccRsh (int shCount, int andmask)
8555 {
8556         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8557         switch(shCount){
8558                 case 0 :
8559                         return; break;
8560                 case 1 :
8561                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8562                         break;
8563                 case 2 :
8564                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8565                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8566                         break;
8567                 case 3 :
8568                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8569                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8570                         break;
8571                 case 4 :
8572                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8573                         break;
8574                 case 5 :
8575                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
8576                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8577                         break;
8578                 case 6 :
8579                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8580                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8581                         break;
8582                 case 7 :
8583                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
8584                         break;
8585         }
8586         
8587         if(andmask)
8588                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
8589         else
8590                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
8591 }
8592
8593 #if 0
8594 /*-----------------------------------------------------------------*/
8595 /* AccSRsh - signed right shift accumulator by known count                 */
8596 /*-----------------------------------------------------------------*/
8597 static void AccSRsh (int shCount)
8598 {
8599     symbol *tlbl ;
8600     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8601     if(shCount != 0){
8602         if(shCount == 1){
8603             pic16_emitcode("mov","c,acc.7");
8604             pic16_emitcode("rrc","a");
8605         } else if(shCount == 2){
8606             pic16_emitcode("mov","c,acc.7");
8607             pic16_emitcode("rrc","a");
8608             pic16_emitcode("mov","c,acc.7");
8609             pic16_emitcode("rrc","a");
8610         } else {
8611             tlbl = newiTempLabel(NULL);
8612             /* rotate right accumulator */
8613             AccRol(8 - shCount);
8614             /* and kill the higher order bits */
8615             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
8616             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
8617             pic16_emitcode("orl","a,#0x%02x",
8618                      (unsigned char)~SRMask[shCount]);
8619             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8620         }
8621     }
8622 }
8623 #endif
8624
8625 /*-----------------------------------------------------------------*/
8626 /* shiftR1Left2Result - shift right one byte from left to result   */
8627 /*-----------------------------------------------------------------*/
8628 static void shiftR1Left2ResultSigned (operand *left, int offl,
8629                                 operand *result, int offr,
8630                                 int shCount)
8631 {
8632   int same;
8633
8634   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8635
8636   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8637
8638   switch(shCount) {
8639   case 1:
8640     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8641     if(same) 
8642       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8643     else {
8644       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8645       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8646     }
8647
8648     break;
8649   case 2:
8650
8651     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8652     if(same) 
8653       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8654     else {
8655       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8656       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8657     }
8658     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
8659     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8660
8661     break;
8662
8663   case 3:
8664     if(same)
8665       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8666     else {
8667       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8668       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8669     }
8670
8671     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8672     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8673     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8674
8675     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8676     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
8677
8678     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8679     break;
8680
8681   case 4:
8682     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8683     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
8684     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8685     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
8686     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8687     break;
8688   case 5:
8689     if(same) {
8690       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
8691     } else {
8692       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
8693       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8694     }
8695     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
8696     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
8697     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER));
8698     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
8699     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
8700     break;
8701
8702   case 6:
8703     if(same) {
8704       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8705       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8706       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
8707       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8708       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
8709       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8710     } else {
8711       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8712       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8713       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8714       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER));
8715       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
8716     }
8717     break;
8718
8719   case 7:
8720     if(same) {
8721       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
8722       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8723       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8724       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8725     } else {
8726       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
8727       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER));
8728       pic16_emitpcode(POC_SETF,  pic16_popGet(AOP(result),offr));
8729     }
8730
8731   default:
8732     break;
8733   }
8734 }
8735
8736 /*-----------------------------------------------------------------*/
8737 /* shiftR1Left2Result - shift right one byte from left to result   */
8738 /*-----------------------------------------------------------------*/
8739 static void shiftR1Left2Result (operand *left, int offl,
8740                                 operand *result, int offr,
8741                                 int shCount, int sign)
8742 {
8743   int same;
8744
8745   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8746
8747   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8748
8749   /* Copy the msb into the carry if signed. */
8750   if(sign) {
8751     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
8752     return;
8753   }
8754
8755
8756
8757   switch(shCount) {
8758   case 1:
8759     emitCLRC;
8760     if(same) 
8761       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8762     else {
8763       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8764       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8765     }
8766     break;
8767   case 2:
8768     emitCLRC;
8769     if(same) {
8770       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8771     } else {
8772       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8773       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8774     }
8775     emitCLRC;
8776     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
8777
8778     break;
8779   case 3:
8780     if(same)
8781       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8782     else {
8783       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8784       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8785     }
8786
8787     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(result),offr));
8788     //pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
8789     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
8790     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8791     break;
8792       
8793   case 4:
8794     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8795     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
8796     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8797     break;
8798
8799   case 5:
8800     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
8801     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e));
8802     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8803     //emitCLRC;
8804     pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr));
8805
8806     break;
8807   case 6:
8808
8809     pic16_emitpcode(POC_RLNCFW,  pic16_popGet(AOP(left),offl));
8810     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81));
8811     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8812     //pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
8813     pic16_emitpcode(POC_RLNCF,   pic16_popGet(AOP(result),offr));
8814     break;
8815
8816   case 7:
8817
8818     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8819     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8820     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8821
8822     break;
8823
8824   default:
8825     break;
8826   }
8827 }
8828
8829 /*-----------------------------------------------------------------*/
8830 /* shiftL1Left2Result - shift left one byte from left to result    */
8831 /*-----------------------------------------------------------------*/
8832 static void shiftL1Left2Result (operand *left, int offl,
8833                                 operand *result, int offr, int shCount)
8834 {
8835   int same;
8836
8837   //    char *l;
8838   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8839
8840   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
8841   DEBUGpic16_emitcode ("; ***","same =  %d",same);
8842     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8843     //    MOVA(l);
8844     /* shift left accumulator */
8845     //AccLsh(shCount, 1); // don't comment out just yet...
8846   //    pic16_aopPut(AOP(result),"a",offr);
8847
8848   switch(shCount) {
8849   case 1:
8850     /* Shift left 1 bit position */
8851     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8852     if(same) {
8853       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
8854     } else {
8855       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
8856       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8857     }
8858     break;
8859   case 2:
8860     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8861     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
8862     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8863     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8864     break;
8865   case 3:
8866     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
8867     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
8868     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8869     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8870     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8871     break;
8872   case 4:
8873     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8874     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8875     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8876     break;
8877   case 5:
8878     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8879     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
8880     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8881     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8882     break;
8883   case 6:
8884     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
8885     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
8886     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8887     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8888     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
8889     break;
8890   case 7:
8891     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
8892     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8893     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8894     break;
8895
8896   default:
8897     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
8898   }
8899
8900 }
8901
8902 /*-----------------------------------------------------------------*/
8903 /* movLeft2Result - move byte from left to result                  */
8904 /*-----------------------------------------------------------------*/
8905 static void movLeft2Result (operand *left, int offl,
8906                             operand *result, int offr)
8907 {
8908   char *l;
8909   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8910   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
8911     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
8912
8913     if (*l == '@' && (IS_AOP_PREG(result))) {
8914       pic16_emitcode("mov","a,%s",l);
8915       pic16_aopPut(AOP(result),"a",offr);
8916     } else {
8917       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
8918       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
8919     }
8920   }
8921 }
8922
8923 /*-----------------------------------------------------------------*/
8924 /* shiftL2Left2Result - shift left two bytes from left to result   */
8925 /*-----------------------------------------------------------------*/
8926 static void shiftL2Left2Result (operand *left, int offl,
8927                                 operand *result, int offr, int shCount)
8928 {
8929   int same = pic16_sameRegs(AOP(result), AOP(left));
8930   int i;
8931
8932   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
8933
8934   if (same && (offl != offr)) { // shift bytes
8935     if (offr > offl) {
8936        for(i=1;i>-1;i--) {
8937          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
8938          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
8939        }
8940     } else { // just treat as different later on
8941                 same = 0;
8942     }
8943   }
8944
8945   if(same) {
8946     switch(shCount) {
8947     case 0:
8948       break;
8949     case 1:
8950     case 2:
8951     case 3:
8952
8953       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
8954       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
8955       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8956
8957       while(--shCount) {
8958                 emitCLRC;
8959                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8960                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8961       }
8962
8963       break;
8964     case 4:
8965     case 5:
8966       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
8967       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
8968       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
8969       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
8970       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
8971       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
8972       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
8973       if(shCount >=5) {
8974                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
8975                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
8976       }
8977       break;
8978     case 6:
8979       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8980       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8981       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
8982       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8984       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
8985       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8986       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
8987       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
8988       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8989       break;
8990     case 7:
8991       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
8992       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
8993       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
8994       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
8995       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
8996     }
8997
8998   } else {
8999     switch(shCount) {
9000     case 0:
9001       break;
9002     case 1:
9003     case 2:
9004     case 3:
9005       /* note, use a mov/add for the shift since the mov has a
9006          chance of getting optimized out */
9007       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
9008       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9009       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9010       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
9011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9012
9013       while(--shCount) {
9014                 emitCLRC;
9015                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9016                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9017       }
9018       break;
9019
9020     case 4:
9021     case 5:
9022       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9023       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
9024       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9025       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9026       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9027       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F));
9028       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
9029       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9030
9031
9032       if(shCount == 5) {
9033                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
9034                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
9035       }
9036       break;
9037     case 6:
9038       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9039       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
9041       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
9042
9043       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
9044       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9045       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
9046       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
9047       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9048       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
9049       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
9050       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9051       break;
9052     case 7:
9053       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9054       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9055       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9056       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
9057       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
9058     }
9059   }
9060
9061 }
9062 /*-----------------------------------------------------------------*/
9063 /* shiftR2Left2Result - shift right two bytes from left to result  */
9064 /*-----------------------------------------------------------------*/
9065 static void shiftR2Left2Result (operand *left, int offl,
9066                                 operand *result, int offr,
9067                                 int shCount, int sign)
9068 {
9069   int same = pic16_sameRegs(AOP(result), AOP(left));
9070   int i;
9071   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
9072
9073   if (same && (offl != offr)) { // shift right bytes
9074     if (offr < offl) {
9075        for(i=0;i<2;i++) {
9076          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
9077          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
9078        }
9079     } else { // just treat as different later on
9080                 same = 0;
9081     }
9082   }
9083
9084   switch(shCount) {
9085   case 0:
9086     break;
9087   case 1:
9088   case 2:
9089   case 3:
9090     if(sign)
9091       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9092     else
9093       emitCLRC;
9094
9095     if(same) {
9096       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9097       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9098     } else {
9099       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
9100       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9101       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
9102       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9103     }
9104
9105     while(--shCount) {
9106       if(sign)
9107                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
9108       else
9109                 emitCLRC;
9110       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
9111       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
9112     }
9113     break;
9114   case 4:
9115   case 5:
9116     if(same) {
9117
9118       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
9119       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
9120       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
9121
9122       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
9123       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
9124       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9125       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9126     } else {
9127       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
9128       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
9129       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
9130
9131       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
9132       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
9133       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
9134       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
9135       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
9136     }
9137
9138     if(shCount >=5) {
9139       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
9140       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
9141     }
9142
9143     if(sign) {
9144       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
9145       pic16_emitpcode(POC_BTFSC, 
9146                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER));
9147       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
9148     }
9149
9150     break;
9151
9152   case 6:
9153     if(same) {
9154
9155       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9156       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9157
9158       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9159       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9160       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
9161       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9162       if(sign) {
9163         pic16_emitpcode(POC_BTFSC, 
9164                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9165         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9166       }
9167       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9168       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
9169       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
9170       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9171     } else {
9172       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9173       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9174       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9175       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9176       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9177       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9178       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
9179       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
9180       if(sign) {
9181         pic16_emitpcode(POC_BTFSC, 
9182                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9183         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
9184       }
9185       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
9186       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
9187
9188         
9189     }
9190
9191     break;
9192   case 7:
9193     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
9194     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
9195     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
9196     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
9197     if(sign) {
9198       emitSKPNC;
9199       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
9200     } else 
9201       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
9202   }
9203 }
9204
9205
9206 /*-----------------------------------------------------------------*/
9207 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
9208 /*-----------------------------------------------------------------*/
9209 static void shiftLLeftOrResult (operand *left, int offl,
9210                                 operand *result, int offr, int shCount)
9211 {
9212     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9213
9214     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9215     /* shift left accumulator */
9216     AccLsh(shCount, 1);
9217     /* or with result */
9218     /* back to result */
9219     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9220 }
9221
9222 /*-----------------------------------------------------------------*/
9223 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
9224 /*-----------------------------------------------------------------*/
9225 static void shiftRLeftOrResult (operand *left, int offl,
9226                                 operand *result, int offr, int shCount)
9227 {
9228     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9229     
9230     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
9231     /* shift right accumulator */
9232     AccRsh(shCount, 1);
9233     /* or with result */
9234     /* back to result */
9235     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
9236 }
9237
9238 /*-----------------------------------------------------------------*/
9239 /* genlshOne - left shift a one byte quantity by known count       */
9240 /*-----------------------------------------------------------------*/
9241 static void genlshOne (operand *result, operand *left, int shCount)
9242 {       
9243     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9244     shiftL1Left2Result(left, LSB, result, LSB, shCount);
9245 }
9246
9247 /*-----------------------------------------------------------------*/
9248 /* genlshTwo - left shift two bytes by known amount != 0           */
9249 /*-----------------------------------------------------------------*/
9250 static void genlshTwo (operand *result,operand *left, int shCount)
9251 {
9252     int size;
9253     
9254     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9255     size = pic16_getDataSize(result);
9256
9257     /* if shCount >= 8 */
9258     if (shCount >= 8) {
9259         shCount -= 8 ;
9260
9261         if (size > 1){
9262             if (shCount)
9263                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9264             else 
9265                 movLeft2Result(left, LSB, result, MSB16);
9266         }
9267         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9268     }
9269
9270     /*  1 <= shCount <= 7 */
9271     else {  
9272         if(size == 1)
9273             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
9274         else 
9275             shiftL2Left2Result(left, LSB, result, LSB, shCount);
9276     }
9277 }
9278
9279 /*-----------------------------------------------------------------*/
9280 /* shiftLLong - shift left one long from left to result            */
9281 /* offr = LSB or MSB16                                             */
9282 /*-----------------------------------------------------------------*/
9283 static void shiftLLong (operand *left, operand *result, int offr )
9284 {
9285     int size = AOP_SIZE(result);
9286     int same = pic16_sameRegs(AOP(left),AOP(result));
9287         int i;
9288
9289     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
9290
9291         if (same && (offr == MSB16)) { //shift one byte
9292                 for(i=size-1;i>=MSB16;i--) {
9293                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
9294                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
9295                 }
9296         } else {
9297                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
9298         }
9299         
9300     if (size > LSB+offr ){
9301                 if (same) {
9302                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
9303                 } else {
9304                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
9305                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
9306                 }
9307          }
9308
9309     if(size > MSB16+offr){
9310                 if (same) {
9311                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
9312                 } else {
9313                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
9314                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
9315                 }
9316     }
9317
9318     if(size > MSB24+offr){
9319                 if (same) {
9320                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
9321                 } else {
9322                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
9323                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
9324                 }
9325     }
9326
9327     if(size > MSB32+offr){
9328                 if (same) {
9329                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
9330                 } else {
9331                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
9332                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
9333                 }
9334     }
9335     if(offr != LSB)
9336                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9337
9338 }
9339
9340 /*-----------------------------------------------------------------*/
9341 /* genlshFour - shift four byte by a known amount != 0             */
9342 /*-----------------------------------------------------------------*/
9343 static void genlshFour (operand *result, operand *left, int shCount)
9344 {
9345     int size;
9346
9347     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9348     size = AOP_SIZE(result);
9349
9350     /* if shifting more that 3 bytes */
9351     if (shCount >= 24 ) {
9352         shCount -= 24;
9353         if (shCount)
9354             /* lowest order of left goes to the highest
9355             order of the destination */
9356             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
9357         else
9358             movLeft2Result(left, LSB, result, MSB32);
9359
9360                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9361                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9362                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
9363
9364         return;
9365     }
9366
9367     /* more than two bytes */
9368     else if ( shCount >= 16 ) {
9369         /* lower order two bytes goes to higher order two bytes */
9370         shCount -= 16;
9371         /* if some more remaining */
9372         if (shCount)
9373             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
9374         else {
9375             movLeft2Result(left, MSB16, result, MSB32);
9376             movLeft2Result(left, LSB, result, MSB24);
9377         }
9378                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9379                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
9380         return;
9381     }    
9382
9383     /* if more than 1 byte */
9384     else if ( shCount >= 8 ) {
9385         /* lower order three bytes goes to higher order  three bytes */
9386         shCount -= 8;
9387         if(size == 2){
9388             if(shCount)
9389                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9390             else
9391                 movLeft2Result(left, LSB, result, MSB16);
9392         }
9393         else{   /* size = 4 */
9394             if(shCount == 0){
9395                 movLeft2Result(left, MSB24, result, MSB32);
9396                 movLeft2Result(left, MSB16, result, MSB24);
9397                 movLeft2Result(left, LSB, result, MSB16);
9398                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9399             }
9400             else if(shCount == 1)
9401                 shiftLLong(left, result, MSB16);
9402             else{
9403                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
9404                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
9405                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
9406                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
9407             }
9408         }
9409     }
9410
9411     /* 1 <= shCount <= 7 */
9412     else if(shCount <= 3)
9413     { 
9414         shiftLLong(left, result, LSB);
9415         while(--shCount >= 1)
9416             shiftLLong(result, result, LSB);
9417     }
9418     /* 3 <= shCount <= 7, optimize */
9419     else{
9420         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
9421         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
9422         shiftL2Left2Result(left, LSB, result, LSB, shCount);
9423     }
9424 }
9425
9426 /*-----------------------------------------------------------------*/
9427 /* genLeftShiftLiteral - left shifting by known count              */
9428 /*-----------------------------------------------------------------*/
9429 void pic16_genLeftShiftLiteral (operand *left,
9430                                  operand *right,
9431                                  operand *result,
9432                                  iCode *ic)
9433 {    
9434     int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
9435     int size;
9436
9437     FENTRY;
9438     DEBUGpic16_emitcode ("; ***","shCount:%d", shCount);
9439     pic16_freeAsmop(right,NULL,ic,TRUE);
9440
9441     pic16_aopOp(left,ic,FALSE);
9442     pic16_aopOp(result,ic,TRUE);
9443
9444     size = getSize(operandType(result));
9445
9446 #if VIEW_SIZE
9447     pic16_emitcode("; shift left ","result %d, left %d",size,
9448              AOP_SIZE(left));
9449 #endif
9450
9451     /* I suppose that the left size >= result size */
9452     if(shCount == 0){
9453         while(size--){
9454             movLeft2Result(left, size, result, size);
9455         }
9456     }
9457
9458     else if(shCount >= (size * 8))
9459         while(size--)
9460             pic16_aopPut(AOP(result),zero,size);
9461     else{
9462         switch (size) {
9463             case 1:
9464                 genlshOne (result,left,shCount);
9465                 break;
9466
9467             case 2:
9468             case 3:
9469                 genlshTwo (result,left,shCount);
9470                 break;
9471
9472             case 4:
9473                 genlshFour (result,left,shCount);
9474                 break;
9475         }
9476     }
9477     pic16_freeAsmop(left,NULL,ic,TRUE);
9478     pic16_freeAsmop(result,NULL,ic,TRUE);
9479 }
9480
9481 /*-----------------------------------------------------------------*
9482  * genMultiAsm - repeat assembly instruction for size of register.
9483  * if endian == 1, then the high byte (i.e base address + size of 
9484  * register) is used first else the low byte is used first;
9485  *-----------------------------------------------------------------*/
9486 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
9487 {
9488
9489   int offset = 0;
9490
9491   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9492
9493   if(!reg)
9494     return;
9495
9496   if(!endian) {
9497     endian = 1;
9498   } else {
9499     endian = -1;
9500     offset = size-1;
9501   }
9502
9503   while(size--) {
9504     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
9505     offset += endian;
9506   }
9507
9508 }
9509
9510 #if !(USE_GENERIC_SIGNED_SHIFT)
9511 /*-----------------------------------------------------------------*/
9512 /* genLeftShift - generates code for left shifting                 */
9513 /*-----------------------------------------------------------------*/
9514 static void genLeftShift (iCode *ic)
9515 {
9516   operand *left,*right, *result;
9517   int size, offset;
9518 //  char *l;
9519   symbol *tlbl , *tlbl1;
9520   pCodeOp *pctemp;
9521
9522   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9523
9524   right = IC_RIGHT(ic);
9525   left  = IC_LEFT(ic);
9526   result = IC_RESULT(ic);
9527
9528   pic16_aopOp(right,ic,FALSE);
9529
9530   /* if the shift count is known then do it 
9531      as efficiently as possible */
9532   if (AOP_TYPE(right) == AOP_LIT) {
9533     pic16_genLeftShiftLiteral (left,right,result,ic);
9534     return ;
9535   }
9536
9537   /* shift count is unknown then we have to form
9538    * a loop. Get the loop count in WREG : Note: we take
9539    * only the lower order byte since shifting
9540    * more than 32 bits make no sense anyway, ( the
9541    * largest size of an object can be only 32 bits ) */
9542   
9543   pic16_aopOp(left,ic,FALSE);
9544   pic16_aopOp(result,ic,FALSE);
9545
9546   /* now move the left to the result if they are not the
9547    * same, and if size > 1,
9548    * and if right is not same to result (!!!) -- VR */
9549   if (!pic16_sameRegs(AOP(left),AOP(result))
9550       && (AOP_SIZE(result) > 1)) {
9551
9552     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9553
9554     size = AOP_SIZE(result);
9555     offset=0;
9556     while (size--) {
9557
9558 #if 0
9559       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9560       if (*l == '@' && (IS_AOP_PREG(result))) {
9561
9562           pic16_emitcode("mov","a,%s",l);
9563           pic16_aopPut(AOP(result),"a",offset);
9564       } else
9565 #endif
9566       {
9567         /* we don't know if left is a literal or a register, take care -- VR */
9568         pic16_mov2f(AOP(result), AOP(left), offset);
9569       }
9570       offset++;
9571     }
9572   }
9573
9574   size = AOP_SIZE(result);
9575
9576   /* if it is only one byte then */
9577   if (size == 1) {
9578     if(optimized_for_speed) {
9579       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9580       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9581       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9582       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9583       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9584       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9585       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9586       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9587       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9588       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9589       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9590       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9591     } else {
9592
9593       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9594
9595       tlbl = newiTempLabel(NULL);
9596
9597 #if 1
9598       /* this is already done, why change it? */
9599       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9600                 pic16_mov2f(AOP(result), AOP(left), 0);
9601       }
9602 #endif
9603
9604       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9605       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9606       pic16_emitpLabel(tlbl->key);
9607       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9608       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9609       emitSKPC;
9610       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9611     }
9612     goto release ;
9613   }
9614     
9615   if (pic16_sameRegs(AOP(left),AOP(result))) {
9616
9617     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9618     
9619     tlbl = newiTempLabel(NULL);
9620     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9621     genMultiAsm(POC_RRCF, result, size,1);
9622     pic16_emitpLabel(tlbl->key);
9623     genMultiAsm(POC_RLCF, result, size,0);
9624     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9625     emitSKPC;
9626     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9627     goto release;
9628   }
9629
9630   //tlbl = newiTempLabel(NULL);
9631   //offset = 0 ;   
9632   //tlbl1 = newiTempLabel(NULL);
9633
9634   //reAdjustPreg(AOP(result));    
9635     
9636   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9637   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9638   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9639   //MOVA(l);
9640   //pic16_emitcode("add","a,acc");         
9641   //pic16_aopPut(AOP(result),"a",offset++);
9642   //while (--size) {
9643   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9644   //  MOVA(l);
9645   //  pic16_emitcode("rlc","a");         
9646   //  pic16_aopPut(AOP(result),"a",offset++);
9647   //}
9648   //reAdjustPreg(AOP(result));
9649
9650   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9651   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9652
9653
9654   tlbl = newiTempLabel(NULL);
9655   tlbl1= newiTempLabel(NULL);
9656
9657   size = AOP_SIZE(result);
9658   offset = 1;
9659
9660   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9661
9662   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9663
9664   /* offset should be 0, 1 or 3 */
9665   
9666   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9667   emitSKPNZ;
9668   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9669
9670   pic16_emitpcode(POC_MOVWF, pctemp);
9671
9672
9673   pic16_emitpLabel(tlbl->key);
9674
9675   emitCLRC;
9676   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9677   while(--size)
9678     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9679
9680   pic16_emitpcode(POC_DECFSZ,  pctemp);
9681   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9682   pic16_emitpLabel(tlbl1->key);
9683
9684   pic16_popReleaseTempReg(pctemp,1);
9685
9686
9687  release:
9688   pic16_freeAsmop (right,NULL,ic,TRUE);
9689   pic16_freeAsmop(left,NULL,ic,TRUE);
9690   pic16_freeAsmop(result,NULL,ic,TRUE);
9691 }
9692 #endif
9693
9694
9695 #if 0
9696 #error old code (left here for reference)
9697 /*-----------------------------------------------------------------*/
9698 /* genLeftShift - generates code for left shifting                 */
9699 /*-----------------------------------------------------------------*/
9700 static void genLeftShift (iCode *ic)
9701 {
9702   operand *left,*right, *result;
9703   int size, offset;
9704   char *l;
9705   symbol *tlbl , *tlbl1;
9706   pCodeOp *pctemp;
9707
9708   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9709
9710   right = IC_RIGHT(ic);
9711   left  = IC_LEFT(ic);
9712   result = IC_RESULT(ic);
9713
9714   pic16_aopOp(right,ic,FALSE);
9715
9716   /* if the shift count is known then do it 
9717      as efficiently as possible */
9718   if (AOP_TYPE(right) == AOP_LIT) {
9719     pic16_genLeftShiftLiteral (left,right,result,ic);
9720     return ;
9721   }
9722
9723   /* shift count is unknown then we have to form 
9724      a loop get the loop count in B : Note: we take
9725      only the lower order byte since shifting
9726      more that 32 bits make no sense anyway, ( the
9727      largest size of an object can be only 32 bits ) */  
9728
9729     
9730   pic16_aopOp(left,ic,FALSE);
9731   pic16_aopOp(result,ic,FALSE);
9732
9733   /* now move the left to the result if they are not the
9734      same */
9735   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
9736       AOP_SIZE(result) > 1) {
9737
9738     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9739
9740     size = AOP_SIZE(result);
9741     offset=0;
9742     while (size--) {
9743       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
9744       if (*l == '@' && (IS_AOP_PREG(result))) {
9745
9746         pic16_emitcode("mov","a,%s",l);
9747         pic16_aopPut(AOP(result),"a",offset);
9748       } else {
9749
9750         /* we don't know if left is a literal or a register, take care -- VR */
9751         pic16_mov2f(AOP(result), AOP(left), offset);
9752       }
9753       offset++;
9754     }
9755   }
9756
9757   size = AOP_SIZE(result);
9758
9759   /* if it is only one byte then */
9760   if (size == 1) {
9761     if(optimized_for_speed) {
9762       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
9763       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
9764       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER));
9765       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9766       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9767       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
9768       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9769       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
9770       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
9771       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
9772       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER));
9773       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
9774     } else {
9775
9776       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9777
9778       tlbl = newiTempLabel(NULL);
9779       if (!pic16_sameRegs(AOP(left),AOP(result))) {
9780                 pic16_mov2f(AOP(result), AOP(left), 0);
9781                 
9782 //              pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
9783 //              pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
9784       }
9785
9786       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9787       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
9788       pic16_emitpLabel(tlbl->key);
9789       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
9790       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9791       emitSKPC;
9792       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9793     }
9794     goto release ;
9795   }
9796     
9797   if (pic16_sameRegs(AOP(left),AOP(result))) {
9798
9799     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9800     
9801     tlbl = newiTempLabel(NULL);
9802     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
9803     genMultiAsm(POC_RRCF, result, size,1);
9804     pic16_emitpLabel(tlbl->key);
9805     genMultiAsm(POC_RLCF, result, size,0);
9806     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
9807     emitSKPC;
9808     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9809     goto release;
9810   }
9811
9812   //tlbl = newiTempLabel(NULL);
9813   //offset = 0 ;   
9814   //tlbl1 = newiTempLabel(NULL);
9815
9816   //reAdjustPreg(AOP(result));    
9817     
9818   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
9819   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
9820   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9821   //MOVA(l);
9822   //pic16_emitcode("add","a,acc");         
9823   //pic16_aopPut(AOP(result),"a",offset++);
9824   //while (--size) {
9825   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
9826   //  MOVA(l);
9827   //  pic16_emitcode("rlc","a");         
9828   //  pic16_aopPut(AOP(result),"a",offset++);
9829   //}
9830   //reAdjustPreg(AOP(result));
9831
9832   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
9833   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
9834
9835
9836   tlbl = newiTempLabel(NULL);
9837   tlbl1= newiTempLabel(NULL);
9838
9839   size = AOP_SIZE(result);
9840   offset = 1;
9841
9842   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
9843
9844   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9845
9846   /* offset should be 0, 1 or 3 */
9847   
9848   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
9849   emitSKPNZ;
9850   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
9851
9852   pic16_emitpcode(POC_MOVWF, pctemp);
9853
9854
9855   pic16_emitpLabel(tlbl->key);
9856
9857   emitCLRC;
9858   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
9859   while(--size)
9860     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
9861
9862   pic16_emitpcode(POC_DECFSZ,  pctemp);
9863   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
9864   pic16_emitpLabel(tlbl1->key);
9865
9866   pic16_popReleaseTempReg(pctemp,1);
9867
9868
9869  release:
9870   pic16_freeAsmop (right,NULL,ic,TRUE);
9871   pic16_freeAsmop(left,NULL,ic,TRUE);
9872   pic16_freeAsmop(result,NULL,ic,TRUE);
9873 }
9874 #endif
9875
9876 /*-----------------------------------------------------------------*/
9877 /* genrshOne - right shift a one byte quantity by known count      */
9878 /*-----------------------------------------------------------------*/
9879 static void genrshOne (operand *result, operand *left,
9880                        int shCount, int sign)
9881 {
9882     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9883     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
9884 }
9885
9886 /*-----------------------------------------------------------------*/
9887 /* genrshTwo - right shift two bytes by known amount != 0          */
9888 /*-----------------------------------------------------------------*/
9889 static void genrshTwo (operand *result,operand *left,
9890                        int shCount, int sign)
9891 {
9892   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
9893   /* if shCount >= 8 */
9894   if (shCount >= 8) {
9895     shCount -= 8 ;
9896     if (shCount)
9897       shiftR1Left2Result(left, MSB16, result, LSB,
9898                          shCount, sign);
9899     else
9900       movLeft2Result(left, MSB16, result, LSB);
9901
9902     pic16_addSign (result, 1, sign);
9903   }
9904
9905   /*  1 <= shCount <= 7 */
9906   else
9907     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
9908 }
9909
9910 /*-----------------------------------------------------------------*/
9911 /* shiftRLong - shift right one long from left to result           */
9912 /* offl = LSB or MSB16                                             */
9913 /*-----------------------------------------------------------------*/
9914 static void shiftRLong (operand *left, int offl,
9915                         operand *result, int sign)
9916 {
9917     int size = AOP_SIZE(result);
9918     int same = pic16_sameRegs(AOP(left),AOP(result));
9919     int i;
9920     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
9921
9922         if (same && (offl == MSB16)) { //shift one byte right
9923                 for(i=MSB16;i<size;i++) {
9924                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
9925                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
9926                 }
9927         }
9928
9929     if(sign)
9930                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
9931         else
9932                 emitCLRC;
9933
9934         if (same) {
9935                 if (offl == LSB)
9936                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
9937         } else {
9938         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
9939         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
9940         }
9941
9942     if(offl == MSB16) {
9943         /* add sign of "a" */
9944         pic16_addSign(result, MSB32, sign);
9945         }
9946
9947         if (same) {
9948         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
9949         } else {
9950         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
9951         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
9952         }
9953         
9954         if (same) {
9955         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
9956         } else {
9957         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
9958         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
9959         }
9960
9961         if (same) {
9962         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
9963         } else {
9964         if(offl == LSB){
9965                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
9966                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
9967         }
9968         }
9969 }
9970
9971 /*-----------------------------------------------------------------*/
9972 /* genrshFour - shift four byte by a known amount != 0             */
9973 /*-----------------------------------------------------------------*/
9974 static void genrshFour (operand *result, operand *left,
9975                         int shCount, int sign)
9976 {
9977   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9978   /* if shifting more that 3 bytes */
9979   if(shCount >= 24 ) {
9980     shCount -= 24;
9981     if(shCount)
9982       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
9983     else
9984       movLeft2Result(left, MSB32, result, LSB);
9985
9986     pic16_addSign(result, MSB16, sign);
9987   }
9988   else if(shCount >= 16){
9989     shCount -= 16;
9990     if(shCount)
9991       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
9992     else{
9993       movLeft2Result(left, MSB24, result, LSB);
9994       movLeft2Result(left, MSB32, result, MSB16);
9995     }
9996     pic16_addSign(result, MSB24, sign);
9997   }
9998   else if(shCount >= 8){
9999     shCount -= 8;
10000     if(shCount == 1)
10001       shiftRLong(left, MSB16, result, sign);
10002     else if(shCount == 0){
10003       movLeft2Result(left, MSB16, result, LSB);
10004       movLeft2Result(left, MSB24, result, MSB16);
10005       movLeft2Result(left, MSB32, result, MSB24);
10006       pic16_addSign(result, MSB32, sign);
10007     }
10008     else{ //shcount >= 2
10009       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
10010       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
10011       /* the last shift is signed */
10012       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
10013       pic16_addSign(result, MSB32, sign);
10014     }
10015   }
10016   else{   /* 1 <= shCount <= 7 */
10017     if(shCount <= 2){
10018       shiftRLong(left, LSB, result, sign);
10019       if(shCount == 2)
10020         shiftRLong(result, LSB, result, sign);
10021     }
10022     else{
10023       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
10024       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
10025       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
10026     }
10027   }
10028 }
10029
10030 /*-----------------------------------------------------------------*/
10031 /* genRightShiftLiteral - right shifting by known count            */
10032 /*-----------------------------------------------------------------*/
10033 static void genRightShiftLiteral (operand *left,
10034                                   operand *right,
10035                                   operand *result,
10036                                   iCode *ic,
10037                                   int sign)
10038 {    
10039   int shCount = abs((int)floatFromVal (AOP(right)->aopu.aop_lit));
10040   int lsize,res_size;
10041
10042   pic16_freeAsmop(right,NULL,ic,TRUE);
10043
10044   pic16_aopOp(left,ic,FALSE);
10045   pic16_aopOp(result,ic,TRUE);
10046
10047   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
10048
10049 #if VIEW_SIZE
10050   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
10051                  AOP_SIZE(left));
10052 #endif
10053
10054   lsize = pic16_getDataSize(left);
10055   res_size = pic16_getDataSize(result);
10056   /* test the LEFT size !!! */
10057
10058   /* I suppose that the left size >= result size */
10059   if(shCount == 0){
10060     assert (res_size <= lsize);
10061     while (res_size--) {
10062       pic16_mov2f (AOP(result), AOP(left), res_size);
10063     } // for
10064   }
10065
10066   else if(shCount >= (lsize * 8)){
10067
10068     if(res_size == 1) {
10069       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
10070       if(sign) {
10071         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10072         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB));
10073       }
10074     } else {
10075
10076       if(sign) {
10077         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
10078         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
10079         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
10080         while(res_size--)
10081           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
10082
10083       } else {
10084
10085         while(res_size--)
10086           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
10087       }
10088     }
10089   } else {
10090
10091     switch (res_size) {
10092     case 1:
10093       genrshOne (result,left,shCount,sign);
10094       break;
10095
10096     case 2:
10097       genrshTwo (result,left,shCount,sign);
10098       break;
10099
10100     case 4:
10101       genrshFour (result,left,shCount,sign);
10102       break;
10103     default :
10104       break;
10105     }
10106
10107   }
10108
10109   pic16_freeAsmop(left,NULL,ic,TRUE);
10110   pic16_freeAsmop(result,NULL,ic,TRUE);
10111 }
10112
10113 #if !(USE_GENERIC_SIGNED_SHIFT)
10114 /*-----------------------------------------------------------------*/
10115 /* genSignedRightShift - right shift of signed number              */
10116 /*-----------------------------------------------------------------*/
10117 static void genSignedRightShift (iCode *ic)
10118 {
10119   operand *right, *left, *result;
10120   int size, offset;
10121   //  char *l;
10122   symbol *tlbl, *tlbl1 ;
10123   pCodeOp *pctemp;
10124
10125   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
10126
10127   /* we do it the hard way put the shift count in b
10128      and loop thru preserving the sign */
10129   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10130
10131   right = IC_RIGHT(ic);
10132   left  = IC_LEFT(ic);
10133   result = IC_RESULT(ic);
10134
10135   pic16_aopOp(right,ic,FALSE);  
10136   pic16_aopOp(left,ic,FALSE);
10137   pic16_aopOp(result,ic,FALSE);
10138
10139
10140   if ( AOP_TYPE(right) == AOP_LIT) {
10141     genRightShiftLiteral (left,right,result,ic,1);
10142     return ;
10143   }
10144   /* shift count is unknown then we have to form 
10145      a loop get the loop count in B : Note: we take
10146      only the lower order byte since shifting
10147      more that 32 bits make no sense anyway, ( the
10148      largest size of an object can be only 32 bits ) */  
10149
10150   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10151   //pic16_emitcode("inc","b");
10152   //pic16_freeAsmop (right,NULL,ic,TRUE);
10153   //pic16_aopOp(left,ic,FALSE);
10154   //pic16_aopOp(result,ic,FALSE);
10155
10156   /* now move the left to the result if they are not the
10157      same */
10158   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10159       AOP_SIZE(result) > 1) {
10160
10161     size = AOP_SIZE(result);
10162     offset=0;
10163     while (size--) { 
10164       /*
10165         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10166         if (*l == '@' && IS_AOP_PREG(result)) {
10167
10168         pic16_emitcode("mov","a,%s",l);
10169         pic16_aopPut(AOP(result),"a",offset);
10170         } else
10171         pic16_aopPut(AOP(result),l,offset);
10172       */
10173       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
10174       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
10175
10176       offset++;
10177     }
10178   }
10179
10180   /* mov the highest order bit to OVR */    
10181   tlbl = newiTempLabel(NULL);
10182   tlbl1= newiTempLabel(NULL);
10183
10184   size = AOP_SIZE(result);
10185   offset = size - 1;
10186
10187   pctemp = pic16_popGetTempReg(1);  /* grab a temporary working register. */
10188
10189   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
10190
10191   /* offset should be 0, 1 or 3 */
10192   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
10193   emitSKPNZ;
10194   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
10195
10196   pic16_emitpcode(POC_MOVWF, pctemp);
10197
10198
10199   pic16_emitpLabel(tlbl->key);
10200
10201   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
10202   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
10203
10204   while(--size) {
10205     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
10206   }
10207
10208   pic16_emitpcode(POC_DECFSZ,  pctemp);
10209   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10210   pic16_emitpLabel(tlbl1->key);
10211
10212   pic16_popReleaseTempReg(pctemp,1);
10213 #if 0
10214   size = AOP_SIZE(result);
10215   offset = size - 1;
10216   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
10217   pic16_emitcode("rlc","a");
10218   pic16_emitcode("mov","ov,c");
10219   /* if it is only one byte then */
10220   if (size == 1) {
10221     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10222     MOVA(l);
10223     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10224     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
10225     pic16_emitcode("mov","c,ov");
10226     pic16_emitcode("rrc","a");
10227     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10228     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10229     pic16_aopPut(AOP(result),"a",0);
10230     goto release ;
10231   }
10232
10233   reAdjustPreg(AOP(result));
10234   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10235   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10236   pic16_emitcode("mov","c,ov");
10237   while (size--) {
10238     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10239     MOVA(l);
10240     pic16_emitcode("rrc","a");         
10241     pic16_aopPut(AOP(result),"a",offset--);
10242   }
10243   reAdjustPreg(AOP(result));
10244   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10245   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10246
10247  release:
10248 #endif
10249
10250   pic16_freeAsmop(left,NULL,ic,TRUE);
10251   pic16_freeAsmop(result,NULL,ic,TRUE);
10252   pic16_freeAsmop(right,NULL,ic,TRUE);
10253 }
10254 #endif
10255
10256 #if !(USE_GENERIC_SIGNED_SHIFT)
10257 #warning This implementation of genRightShift() is incomplete!
10258 /*-----------------------------------------------------------------*/
10259 /* genRightShift - generate code for right shifting                */
10260 /*-----------------------------------------------------------------*/
10261 static void genRightShift (iCode *ic)
10262 {
10263     operand *right, *left, *result;
10264     sym_link *letype ;
10265     int size, offset;
10266     char *l;
10267     symbol *tlbl, *tlbl1 ;
10268
10269     /* if signed then we do it the hard way preserve the
10270     sign bit moving it inwards */
10271     letype = getSpec(operandType(IC_LEFT(ic)));
10272     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10273
10274     if (!SPEC_USIGN(letype)) {
10275         genSignedRightShift (ic);
10276         return ;
10277     }
10278
10279     /* signed & unsigned types are treated the same : i.e. the
10280     signed is NOT propagated inwards : quoting from the
10281     ANSI - standard : "for E1 >> E2, is equivalent to division
10282     by 2**E2 if unsigned or if it has a non-negative value,
10283     otherwise the result is implementation defined ", MY definition
10284     is that the sign does not get propagated */
10285
10286     right = IC_RIGHT(ic);
10287     left  = IC_LEFT(ic);
10288     result = IC_RESULT(ic);
10289
10290     pic16_aopOp(right,ic,FALSE);
10291
10292     /* if the shift count is known then do it 
10293     as efficiently as possible */
10294     if (AOP_TYPE(right) == AOP_LIT) {
10295         genRightShiftLiteral (left,right,result,ic, 0);
10296         return ;
10297     }
10298
10299     /* shift count is unknown then we have to form 
10300     a loop get the loop count in B : Note: we take
10301     only the lower order byte since shifting
10302     more that 32 bits make no sense anyway, ( the
10303     largest size of an object can be only 32 bits ) */  
10304
10305     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
10306     pic16_emitcode("inc","b");
10307     pic16_aopOp(left,ic,FALSE);
10308     pic16_aopOp(result,ic,FALSE);
10309
10310     /* now move the left to the result if they are not the
10311     same */
10312     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
10313         AOP_SIZE(result) > 1) {
10314
10315         size = AOP_SIZE(result);
10316         offset=0;
10317         while (size--) {
10318             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
10319             if (*l == '@' && IS_AOP_PREG(result)) {
10320
10321                 pic16_emitcode("mov","a,%s",l);
10322                 pic16_aopPut(AOP(result),"a",offset);
10323             } else
10324                 pic16_aopPut(AOP(result),l,offset);
10325             offset++;
10326         }
10327     }
10328
10329     tlbl = newiTempLabel(NULL);
10330     tlbl1= newiTempLabel(NULL);
10331     size = AOP_SIZE(result);
10332     offset = size - 1;
10333
10334     /* if it is only one byte then */
10335     if (size == 1) {
10336
10337       tlbl = newiTempLabel(NULL);
10338       if (!pic16_sameRegs(AOP(left),AOP(result))) {
10339         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
10340         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
10341       }
10342
10343       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
10344       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
10345       pic16_emitpLabel(tlbl->key);
10346       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
10347       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
10348       emitSKPC;
10349       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
10350
10351       goto release ;
10352     }
10353
10354     reAdjustPreg(AOP(result));
10355     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
10356     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
10357     CLRC;
10358     while (size--) {
10359         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
10360         MOVA(l);
10361         pic16_emitcode("rrc","a");         
10362         pic16_aopPut(AOP(result),"a",offset--);
10363     }
10364     reAdjustPreg(AOP(result));
10365
10366     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
10367     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
10368
10369 release:
10370     pic16_freeAsmop(left,NULL,ic,TRUE);
10371     pic16_freeAsmop (right,NULL,ic,TRUE);
10372     pic16_freeAsmop(result,NULL,ic,TRUE);
10373 }
10374 #endif
10375
10376 #if (USE_GENERIC_SIGNED_SHIFT)
10377 /*-----------------------------------------------------------------*/
10378 /* genGenericShift - generates code for left or right shifting     */
10379 /*-----------------------------------------------------------------*/
10380 static void genGenericShift (iCode *ic, int isShiftLeft) {
10381   operand *left,*right, *result;
10382   int offset;
10383   int sign, signedCount;
10384   symbol *label_complete, *label_loop_pos, *label_loop_neg, *label_negative;
10385   PIC_OPCODE pos_shift, neg_shift;
10386
10387   FENTRY;
10388
10389   right = IC_RIGHT(ic);
10390   left  = IC_LEFT(ic);
10391   result = IC_RESULT(ic);
10392
10393   pic16_aopOp(right,ic,FALSE);
10394   pic16_aopOp(left,ic,FALSE);
10395   pic16_aopOp(result,ic,TRUE);
10396
10397   sign = !SPEC_USIGN(operandType (left));
10398   signedCount = !SPEC_USIGN(operandType (right));
10399
10400   /* if the shift count is known then do it 
10401      as efficiently as possible */
10402   if (AOP_TYPE(right) == AOP_LIT) {
10403     long lit = (long)floatFromVal(AOP(right)->aopu.aop_lit);
10404     if (signedCount && lit < 0) { lit = -lit; isShiftLeft = !isShiftLeft; }
10405     // we should modify right->aopu.aop_lit here!
10406     // Instead we use abs(shCount) in genXXXShiftLiteral()...
10407     // lit > 8*size is handled in pic16_genXXXShiftLiteral()
10408     if (isShiftLeft)
10409       pic16_genLeftShiftLiteral (left,right,result,ic);
10410     else
10411       genRightShiftLiteral (left,right,result,ic, sign);
10412
10413     goto release;
10414   } // if (right is literal)
10415
10416   /* shift count is unknown then we have to form a loop.
10417    * Note: we take only the lower order byte since shifting
10418    * more than 32 bits make no sense anyway, ( the
10419    * largest size of an object can be only 32 bits )
10420    * Note: we perform arithmetic shifts if the left operand is
10421    * signed and we do an (effective) right shift, i. e. we
10422    * shift in the sign bit from the left. */
10423    
10424   label_complete = newiTempLabel ( NULL );
10425   label_loop_pos = newiTempLabel ( NULL );
10426   label_loop_neg = NULL;
10427   label_negative = NULL;
10428   pos_shift = isShiftLeft ? POC_RLCF : POC_RRCF;
10429   neg_shift = isShiftLeft ? POC_RRCF : POC_RLCF;
10430
10431   if (signedCount) {
10432     // additional labels needed
10433     label_loop_neg = newiTempLabel ( NULL );
10434     label_negative = newiTempLabel ( NULL );
10435   } // if
10436
10437   // copy source to result -- this will effectively truncate the left operand to the size of result!
10438   // (e.g. char c = 0x100 << -3 will become c = 0x00 >> 3 == 0x00 instad of 0x20)
10439   // This is fine, as it only occurs for left shifting with negative count which is not standardized!
10440   for (offset=0; offset < min(AOP_SIZE(left), AOP_SIZE(result)); offset++) {
10441     pic16_mov2f (AOP(result),AOP(left), offset);
10442   } // for
10443
10444   // if result is longer than left, fill with zeros (or sign)
10445   if (AOP_SIZE(left) < AOP_SIZE(result)) {
10446     if (sign && AOP_SIZE(left) > 0) {
10447       // shift signed operand -- fill with sign
10448       pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
10449       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(left)-1), 7));
10450       pic16_emitpcode (POC_MOVLW, pic16_popGetLit (0xFF));
10451       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10452         pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), offset));
10453       } // for
10454     } else {
10455       // shift unsigned operand -- fill result with zeros
10456       for (offset=AOP_SIZE(left); offset < AOP_SIZE(result); offset++) {
10457         pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
10458       } // for
10459     }
10460   } // if (size mismatch)
10461
10462   pic16_mov2w (AOP(right), 0);
10463   pic16_emitpcode (POC_BZ, pic16_popGetLabel (label_complete->key));
10464   if (signedCount) pic16_emitpcode (POC_BN, pic16_popGetLabel (label_negative->key));
10465   
10466 #if 0
10467   // perform a shift by one (shift count is positive)
10468   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10469   // 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])
10470   pic16_emitpLabel (label_loop_pos->key);
10471   emitCLRC;
10472   if (sign && (pos_shift == POC_RRCF)) {
10473     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10474     emitSETC;
10475   } // if
10476   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10477   pic16_emitpcode (POC_DECFSZ, pic16_popCopyReg (&pic16_pc_wreg));
10478   pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_loop_pos->key));
10479 #else
10480   // perform a shift by one (shift count is positive)
10481   // cycles used for shifting {unsigned,signed} values on n bytes by [unsigned,signed] shift count c>0:
10482   // 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])
10483   // This variant is slower for 0<c<3, equally fast for c==3, and faster for 3<c.
10484   pic16_emitpcode (POC_NEGF, pic16_popCopyReg (&pic16_pc_wreg));
10485   emitCLRC;
10486   pic16_emitpLabel (label_loop_pos->key);
10487   if (sign && (pos_shift == POC_RRCF)) {
10488     pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10489     emitSETC;
10490   } // if
10491   genMultiAsm (pos_shift, result, AOP_SIZE(result), pos_shift == POC_RRCF);
10492   //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10493   pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10494   pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_pos->key));
10495 #endif
10496
10497   if (signedCount) {
10498     pic16_emitpcode (POC_BRA, pic16_popGetLabel (label_complete->key));
10499
10500     pic16_emitpLabel (label_negative->key);
10501     // perform a shift by -1 (shift count is negative)
10502     // 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)
10503     emitCLRC;
10504     pic16_emitpLabel (label_loop_neg->key);
10505     if (sign && (neg_shift == POC_RRCF)) {
10506       pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), AOP_SIZE(result)-1), 7));
10507       emitSETC;
10508     } // if
10509     genMultiAsm (neg_shift, result, AOP_SIZE(result), neg_shift == POC_RRCF);
10510     //pic16_emitpcode (POC_INCF, pic16_popCopyReg (&pic16_pc_wreg)); // gpsim does not like this...
10511     pic16_emitpcode (POC_ADDLW, pic16_popGetLit (0x01));
10512     pic16_emitpcode (POC_BNC, pic16_popGetLabel (label_loop_neg->key));
10513   } // if (signedCount)
10514
10515   pic16_emitpLabel (label_complete->key);
10516
10517 release:
10518   pic16_freeAsmop (right,NULL,ic,TRUE);
10519   pic16_freeAsmop(left,NULL,ic,TRUE);
10520   pic16_freeAsmop(result,NULL,ic,TRUE);
10521 }
10522
10523 static void genLeftShift (iCode *ic) {
10524   genGenericShift (ic, 1);
10525 }
10526
10527 static void genRightShift (iCode *ic) {
10528   genGenericShift (ic, 0);
10529 }
10530 #endif
10531
10532
10533 /* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */
10534 void pic16_loadFSR0(operand *op, int lit)
10535 {
10536   if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) {
10537     if (AOP_TYPE(op) == AOP_LIT) {
10538       /* handle 12 bit integers correctly */
10539       unsigned int val = (unsigned int)floatFromVal(AOP(op)->aopu.aop_lit);
10540       if ((val & 0x0fff) != val) {
10541         fprintf (stderr, "WARNING: Accessing memory at 0x%x truncated to 0x%x.\n",
10542                 val, (val & 0x0fff) );
10543         val &= 0x0fff;
10544       }
10545       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetLit12(val)));
10546     } else {
10547       pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
10548     }
10549   } else {
10550     assert (!IS_SYMOP(op) || !OP_SYMBOL(op)->remat);
10551     // set up FSR0 with address of result
10552     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10553     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(op),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10554   }
10555 }
10556
10557 /*----------------------------------------------------------------*/
10558 /* pic16_derefPtr - move one byte from the location ptr points to */
10559 /*                  to WREG (doWrite == 0) or one byte from WREG   */
10560 /*                  to the location ptr points to (doWrite != 0)   */
10561 /*----------------------------------------------------------------*/
10562 static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_setup)
10563 {
10564   if (!IS_PTR(operandType(ptr)))
10565   {
10566     if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(ptr), 0));
10567     else pic16_mov2w (AOP(ptr), 0);
10568     return;
10569   }
10570
10571   //assert (IS_DECL(operandType(ptr)) && (p_type == DCL_TYPE(operandType(ptr))));
10572   /* We might determine pointer type right here: */
10573   p_type = DCL_TYPE(operandType(ptr));
10574
10575   switch (p_type) {
10576     case FPOINTER:
10577     case POINTER:
10578       if (!fsr0_setup || !*fsr0_setup)
10579       {
10580         pic16_loadFSR0( ptr, 0 );
10581         if (fsr0_setup) *fsr0_setup = 1;
10582       }
10583       if (doWrite)
10584         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10585       else
10586         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10587       break;
10588
10589     case GPOINTER:
10590       if (AOP(ptr)->aopu.aop_reg[2]) {
10591         if (doWrite) pic16_emitpcode (POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
10592         // prepare call to __gptrget1, this is actually genGenPointerGet(result, WREG, ?ic?)
10593         mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(ptr), 0);
10594         mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(ptr), 1);
10595         pic16_mov2w(AOP(ptr), 2);
10596         pic16_callGenericPointerRW(doWrite, 1);
10597       } else {
10598         // data pointer (just 2 byte given)
10599         if (!fsr0_setup || !*fsr0_setup)
10600         {
10601           pic16_loadFSR0( ptr, 0 );
10602           if (fsr0_setup) *fsr0_setup = 1;
10603         }
10604         if (doWrite)
10605           pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10606         else
10607           pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
10608       }
10609       break;
10610
10611     default:
10612       assert (0 && "invalid pointer type specified");
10613       break;
10614   }
10615 }
10616
10617 /*-----------------------------------------------------------------*/
10618 /* genUnpackBits - generates code for unpacking bits               */
10619 /*-----------------------------------------------------------------*/
10620 static void genUnpackBits (operand *result, operand *left, char *rname, int ptype)
10621 {    
10622   int shCnt ;
10623   sym_link *etype, *letype;
10624   int blen=0, bstr=0;
10625   int lbstr;
10626   int same;
10627   pCodeOp *op;
10628
10629   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10630   etype = getSpec(operandType(result));
10631   letype = getSpec(operandType(left));
10632
10633   //    if(IS_BITFIELD(etype)) {
10634   blen = SPEC_BLEN(etype);
10635   bstr = SPEC_BSTR(etype);
10636   //    }
10637
10638   lbstr = SPEC_BSTR( letype );
10639
10640   DEBUGpic16_emitcode ("; ***","%s  %d - reading %s bitfield int %s destination",__FUNCTION__,__LINE__,
10641       SPEC_USIGN(OP_SYM_ETYPE(left)) ? "an unsigned" : "a signed", SPEC_USIGN(OP_SYM_TYPE(result)) ? "an unsigned" : "a signed");
10642
10643 #if 1
10644   if((blen == 1) && (bstr < 8)
10645       && (!IS_PTR(operandType(left)) || IS_DIRECT(left) || PIC_IS_DATA_PTR(operandType(left)))) {
10646     /* it is a single bit, so use the appropriate bit instructions */
10647     DEBUGpic16_emitcode (";","%s %d optimize bit read",__FUNCTION__,__LINE__);
10648
10649     same = pic16_sameRegs(AOP(left),AOP(result));
10650     op = (same ? pic16_popCopyReg(&pic16_pc_wreg) : pic16_popGet (AOP(result),0));
10651     pic16_emitpcode(POC_CLRF, op);
10652
10653     if(!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10654       /* workaround to reduce the extra lfsr instruction */
10655       pic16_emitpcode(POC_BTFSC,
10656           pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bstr));
10657     } else {
10658       assert (PIC_IS_DATA_PTR (operandType(left)));
10659       pic16_loadFSR0 (left, 0);
10660       pic16_emitpcode(POC_BTFSC,
10661           pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
10662     }
10663
10664     if (SPEC_USIGN(OP_SYM_ETYPE(left))) {
10665       /* unsigned bitfields result in either 0 or 1 */
10666       pic16_emitpcode(POC_INCF, op);
10667     } else {
10668       /* signed bitfields result in either 0 or -1 */
10669       pic16_emitpcode(POC_DECF, op);
10670     }
10671     if (same) {
10672       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0 ));
10673     }
10674
10675     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10676     return;
10677   }
10678
10679 #endif
10680
10681   if (!IS_PTR(operandType(left)) || IS_DIRECT(left)) {
10682     // access symbol directly
10683     pic16_mov2w (AOP(left), 0);
10684   } else {
10685     pic16_derefPtr (left, ptype, 0, NULL);
10686   }
10687
10688   /* if we have bitdisplacement then it fits   */
10689   /* into this byte completely or if length is */
10690   /* less than a byte                          */
10691   if ((shCnt = SPEC_BSTR(etype)) || (SPEC_BLEN(etype) <= 8))  {
10692
10693     /* shift right acc */
10694     AccRsh(shCnt, 0);
10695
10696     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
10697           (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
10698
10699     /* VR -- normally I would use the following, but since we use the hack,
10700      * to avoid the masking from AccRsh, why not mask it right now? */
10701
10702     /*
10703        pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
10704      */
10705
10706     /* extend signed bitfields to 8 bits */
10707     if (!SPEC_USIGN(OP_SYM_ETYPE(left)) && (bstr + blen < 8))
10708     {
10709       assert (blen + bstr > 0);
10710       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr + blen - 1));
10711       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xFF << (bstr + blen)));
10712     }
10713
10714     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10715
10716     pic16_addSign (result, 1, !SPEC_USIGN(OP_SYM_TYPE(result)));
10717     return ;
10718   }
10719
10720   fprintf(stderr, "SDCC pic16 port error: the port currently does not support *reading*\n");
10721   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
10722   exit(EXIT_FAILURE);
10723
10724   return ;
10725 }
10726
10727
10728 static void genDataPointerGet(operand *left, operand *result, iCode *ic)
10729 {
10730   int size, offset = 0, leoffset=0 ;
10731
10732         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10733         pic16_aopOp(result, ic, TRUE);
10734
10735         FENTRY;
10736
10737         size = AOP_SIZE(result);
10738 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
10739
10740
10741 #if 1
10742         if(!strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE),
10743                 pic16_aopGet(AOP(left), 0, TRUE, FALSE))) {
10744                 DEBUGpic16_emitcode("; ***", "left and result names are same, skipping moving");
10745                 goto release;
10746         }
10747 #endif
10748
10749         if(AOP(left)->aopu.pcop->type == PO_DIR)
10750                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
10751
10752         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
10753
10754         while (size--) {
10755                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
10756                 
10757 //              pic16_DumpOp("(result)",result);
10758                 if(is_LitAOp(AOP(result))) {
10759                         pic16_mov2w(AOP(left), offset); // patch 8
10760                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
10761                 } else {
10762                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
10763                                 pic16_popGet(AOP(left), offset), //patch 8
10764                                 pic16_popGet(AOP(result), offset)));
10765                 }
10766
10767                 offset++;
10768                 leoffset++;
10769         }
10770
10771 release:
10772     pic16_freeAsmop(result,NULL,ic,TRUE);
10773 }
10774
10775
10776
10777 /*-----------------------------------------------------------------*/
10778 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
10779 /*-----------------------------------------------------------------*/
10780 static void genNearPointerGet (operand *left, 
10781                                operand *result, 
10782                                iCode *ic)
10783 {
10784 //  asmop *aop = NULL;
10785   //regs *preg = NULL ;
10786   sym_link *rtype, *retype;
10787   sym_link *ltype, *letype;
10788
10789     FENTRY;
10790     
10791     rtype = operandType(result);
10792     retype= getSpec(rtype);
10793     ltype = operandType(left);
10794     letype= getSpec(ltype);
10795     
10796     pic16_aopOp(left,ic,FALSE);
10797
10798 //    pic16_DumpOp("(left)",left);
10799 //    pic16_DumpOp("(result)",result);
10800
10801     /* if left is rematerialisable and
10802      * result is not bit variable type and
10803      * the left is pointer to data space i.e
10804      * lower 128 bytes of space */
10805     
10806     if (AOP_TYPE(left) == AOP_PCODE
10807       && !IS_BITFIELD(retype)
10808       && DCL_TYPE(ltype) == POINTER) {
10809
10810         genDataPointerGet (left,result,ic);
10811         pic16_freeAsmop(left, NULL, ic, TRUE);
10812         return ;
10813     }
10814     
10815     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10816     pic16_aopOp (result,ic,TRUE);
10817     
10818     DEBUGpic16_pic16_AopType(__LINE__, left, NULL, result);
10819
10820 #if 1
10821     if(IS_BITFIELD( retype )
10822       && (SPEC_BLEN(operandType(result))==1)
10823     ) {
10824       iCode *nextic;
10825       pCodeOp *jop;
10826       int bitstrt, bytestrt;
10827
10828         /* if this is bitfield of size 1, see if we are checking the value
10829          * of a single bit in an if-statement,
10830          * if yes, then don't generate usual code, but execute the
10831          * genIfx directly -- VR */
10832
10833         nextic = ic->next;
10834
10835         /* CHECK: if next iCode is IFX
10836          * and current result operand is nextic's conditional operand
10837          * and current result operand live ranges ends at nextic's key number
10838          */
10839         if((nextic->op == IFX)
10840           && (result == IC_COND(nextic))
10841           && (OP_LIVETO(result) == nextic->seq)
10842           && (OP_SYMBOL(left)->remat)   // below fails for "if (p->bitfield)"
10843           ) {
10844             /* everything is ok then */
10845             /* find a way to optimize the genIfx iCode */
10846
10847             bytestrt = SPEC_BSTR(operandType(result))/8;
10848             bitstrt = SPEC_BSTR(operandType(result))%8;
10849             
10850             jop = pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), 0), bitstrt);
10851
10852             genIfxpCOpJump(nextic, jop);
10853             
10854             pic16_freeAsmop(left, NULL, ic, TRUE);
10855             pic16_freeAsmop(result, NULL, ic, TRUE);
10856             return;
10857         }
10858     }
10859 #endif
10860
10861     /* if bitfield then unpack the bits */
10862     if (IS_BITFIELD(letype)) 
10863       genUnpackBits (result, left, NULL, POINTER);
10864     else {
10865       /* we have can just get the values */
10866       int size = AOP_SIZE(result);
10867       int offset = 0;   
10868         
10869       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10870
10871       pic16_loadFSR0( left, 0 );
10872
10873       while(size--) {
10874         if(size) {
10875           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
10876                 pic16_popGet(AOP(result), offset++)));
10877         } else {
10878           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
10879                 pic16_popGet(AOP(result), offset++)));
10880         }
10881       }
10882     }
10883
10884 #if 0
10885     /* now some housekeeping stuff */
10886     if (aop) {
10887       /* we had to allocate for this iCode */
10888       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10889       pic16_freeAsmop(NULL,aop,ic,TRUE);
10890     } else { 
10891       /* we did not allocate which means left
10892        * already in a pointer register, then
10893        * if size > 0 && this could be used again
10894        * we have to point it back to where it 
10895        * belongs */
10896       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10897       if (AOP_SIZE(result) > 1
10898         && !OP_SYMBOL(left)->remat
10899         && ( OP_SYMBOL(left)->liveTo > ic->seq
10900             || ic->depth )) {
10901 //        int size = AOP_SIZE(result) - 1;
10902 //        while (size--)
10903 //          pic16_emitcode("dec","%s",rname);
10904         }
10905     }
10906 #endif
10907
10908     /* done */
10909     pic16_freeAsmop(left,NULL,ic,TRUE);
10910     pic16_freeAsmop(result,NULL,ic,TRUE);
10911 }
10912
10913 /*-----------------------------------------------------------------*/
10914 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
10915 /*-----------------------------------------------------------------*/
10916 static void genPagedPointerGet (operand *left, 
10917                                operand *result, 
10918                                iCode *ic)
10919 {
10920     asmop *aop = NULL;
10921     regs *preg = NULL ;
10922     char *rname ;
10923     sym_link *rtype, *retype;    
10924
10925     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10926
10927     rtype = operandType(result);
10928     retype= getSpec(rtype);
10929     
10930     pic16_aopOp(left,ic,FALSE);
10931
10932   /* if the value is already in a pointer register
10933        then don't need anything more */
10934     if (!AOP_INPREG(AOP(left))) {
10935         /* otherwise get a free pointer register */
10936         aop = newAsmop(0);
10937         preg = getFreePtr(ic,&aop,FALSE);
10938         pic16_emitcode("mov","%s,%s",
10939                 preg->name,
10940                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
10941         rname = preg->name ;
10942     } else
10943         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
10944     
10945     pic16_freeAsmop(left,NULL,ic,TRUE);
10946     pic16_aopOp (result,ic,TRUE);
10947
10948     /* if bitfield then unpack the bits */
10949     if (IS_BITFIELD(retype)) 
10950         genUnpackBits (result,left,rname,PPOINTER);
10951     else {
10952         /* we have can just get the values */
10953         int size = AOP_SIZE(result);
10954         int offset = 0 ;        
10955         
10956         while (size--) {
10957             
10958             pic16_emitcode("movx","a,@%s",rname);
10959             pic16_aopPut(AOP(result),"a",offset);
10960             
10961             offset++ ;
10962             
10963             if (size)
10964                 pic16_emitcode("inc","%s",rname);
10965         }
10966     }
10967
10968     /* now some housekeeping stuff */
10969     if (aop) {
10970         /* we had to allocate for this iCode */
10971         pic16_freeAsmop(NULL,aop,ic,TRUE);
10972     } else { 
10973         /* we did not allocate which means left
10974            already in a pointer register, then
10975            if size > 0 && this could be used again
10976            we have to point it back to where it 
10977            belongs */
10978         if (AOP_SIZE(result) > 1 &&
10979             !OP_SYMBOL(left)->remat &&
10980             ( OP_SYMBOL(left)->liveTo > ic->seq ||
10981               ic->depth )) {
10982             int size = AOP_SIZE(result) - 1;
10983             while (size--)
10984                 pic16_emitcode("dec","%s",rname);
10985         }
10986     }
10987
10988     /* done */
10989     pic16_freeAsmop(result,NULL,ic,TRUE);
10990     
10991         
10992 }
10993
10994 #if 0
10995 /* This code is not adjusted to PIC16 and fails utterly.
10996  * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */
10997
10998 /*-----------------------------------------------------------------*/
10999 /* genFarPointerGet - gget value from far space                    */
11000 /*-----------------------------------------------------------------*/
11001 static void genFarPointerGet (operand *left,
11002                               operand *result, iCode *ic)
11003 {
11004     int size, offset ;
11005     sym_link *retype = getSpec(operandType(result));
11006
11007     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11008
11009     pic16_aopOp(left,ic,FALSE);
11010
11011     /* if the operand is already in dptr 
11012     then we do nothing else we move the value to dptr */
11013     if (AOP_TYPE(left) != AOP_STR) {
11014         /* if this is remateriazable */
11015         if (AOP_TYPE(left) == AOP_IMMD)
11016             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11017         else { /* we need to get it byte by byte */
11018             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11019             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11020             if (options.model == MODEL_FLAT24)
11021             {
11022                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11023             }
11024         }
11025     }
11026     /* so dptr know contains the address */
11027     pic16_freeAsmop(left,NULL,ic,TRUE);
11028     pic16_aopOp(result,ic,TRUE);
11029
11030     /* if bit then unpack */
11031     if (IS_BITFIELD(retype)) 
11032         genUnpackBits(result,left,"dptr",FPOINTER);
11033     else {
11034         size = AOP_SIZE(result);
11035         offset = 0 ;
11036
11037         while (size--) {
11038             pic16_emitcode("movx","a,@dptr");
11039             pic16_aopPut(AOP(result),"a",offset++);
11040             if (size)
11041                 pic16_emitcode("inc","dptr");
11042         }
11043     }
11044
11045     pic16_freeAsmop(result,NULL,ic,TRUE);
11046 }
11047 #endif
11048
11049 #if 0
11050 /*-----------------------------------------------------------------*/
11051 /* genCodePointerGet - get value from code space                  */
11052 /*-----------------------------------------------------------------*/
11053 static void genCodePointerGet (operand *left,
11054                                 operand *result, iCode *ic)
11055 {
11056     int size, offset ;
11057     sym_link *retype = getSpec(operandType(result));
11058
11059     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11060
11061     pic16_aopOp(left,ic,FALSE);
11062
11063     /* if the operand is already in dptr 
11064     then we do nothing else we move the value to dptr */
11065     if (AOP_TYPE(left) != AOP_STR) {
11066         /* if this is remateriazable */
11067         if (AOP_TYPE(left) == AOP_IMMD)
11068             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
11069         else { /* we need to get it byte by byte */
11070             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
11071             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
11072             if (options.model == MODEL_FLAT24)
11073             {
11074                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
11075             }
11076         }
11077     }
11078     /* so dptr know contains the address */
11079     pic16_freeAsmop(left,NULL,ic,TRUE);
11080     pic16_aopOp(result,ic,FALSE);
11081
11082     /* if bit then unpack */
11083     if (IS_BITFIELD(retype)) 
11084         genUnpackBits(result,left,"dptr",CPOINTER);
11085     else {
11086         size = AOP_SIZE(result);
11087         offset = 0 ;
11088
11089         while (size--) {
11090             pic16_emitcode("clr","a");
11091             pic16_emitcode("movc","a,@a+dptr");
11092             pic16_aopPut(AOP(result),"a",offset++);
11093             if (size)
11094                 pic16_emitcode("inc","dptr");
11095         }
11096     }
11097
11098     pic16_freeAsmop(result,NULL,ic,TRUE);
11099 }
11100 #endif
11101
11102 #if 0
11103 /*-----------------------------------------------------------------*/
11104 /* genGenPointerGet - gget value from generic pointer space        */
11105 /*-----------------------------------------------------------------*/
11106 static void genGenPointerGet (operand *left,
11107                               operand *result, iCode *ic)
11108 {
11109   int size, offset, lit;
11110   sym_link *retype = getSpec(operandType(result));
11111
11112         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11113         pic16_aopOp(left,ic,FALSE);
11114         pic16_aopOp(result,ic,FALSE);
11115         size = AOP_SIZE(result);
11116
11117         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11118
11119         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11120
11121                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11122                 // load FSR0 from immediate
11123                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11124
11125 //              pic16_loadFSR0( left );
11126
11127                 offset = 0;
11128                 while(size--) {
11129                         if(size) {
11130                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11131                         } else {
11132                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11133                         }
11134                         offset++;
11135                 }
11136                 goto release;
11137
11138         }
11139         else { /* we need to get it byte by byte */
11140                 // set up FSR0 with address from left
11141                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11142                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11143                 
11144                 offset = 0 ;
11145
11146                 while(size--) {
11147                         if(size) {
11148                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11149                         } else {
11150                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11151                         }
11152                         offset++;
11153                 }
11154                 goto release;
11155         }
11156
11157   /* if bit then unpack */
11158         if (IS_BITFIELD(retype)) 
11159                 genUnpackBits(result,left,"BAD",GPOINTER);
11160
11161         release:
11162         pic16_freeAsmop(left,NULL,ic,TRUE);
11163         pic16_freeAsmop(result,NULL,ic,TRUE);
11164
11165 }
11166 #endif
11167
11168
11169 /*-----------------------------------------------------------------*/
11170 /* genGenPointerGet - gget value from generic pointer space        */
11171 /*-----------------------------------------------------------------*/
11172 static void genGenPointerGet (operand *left,
11173                               operand *result, iCode *ic)
11174 {
11175   int size, offset, lit;
11176   sym_link *letype = getSpec(operandType(left));
11177
11178     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11179     pic16_aopOp(left,ic,FALSE);
11180     pic16_aopOp(result,ic,TRUE);
11181     size = AOP_SIZE(result);
11182
11183     DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11184   
11185     /* if bit then unpack */
11186     if (IS_BITFIELD(letype)) {
11187       genUnpackBits(result,left,"BAD",GPOINTER);
11188       goto release;
11189     }
11190
11191     if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
11192
11193       lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
11194       // load FSR0 from immediate
11195       pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11196
11197       werror(W_POSSBUG2, __FILE__, __LINE__);
11198
11199       offset = 0;
11200       while(size--) {
11201         if(size) {
11202           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
11203         } else {
11204           pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
11205         }
11206         offset++;
11207       }
11208
11209       goto release;
11210
11211     } else { /* we need to get it byte by byte */
11212
11213       /* set up WREG:PRODL:FSR0L with address from left */
11214       mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0);
11215       mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1);
11216       pic16_mov2w(AOP(left), 2);
11217       pic16_callGenericPointerRW(0, size);
11218       
11219       assignResultValue(result, 1);
11220       
11221       goto release;
11222     }
11223
11224 release:
11225   pic16_freeAsmop(left,NULL,ic,TRUE);
11226   pic16_freeAsmop(result,NULL,ic,TRUE);
11227 }
11228
11229 /*-----------------------------------------------------------------*/
11230 /* genConstPointerGet - get value from const generic pointer space */
11231 /*-----------------------------------------------------------------*/
11232 static void genConstPointerGet (operand *left,
11233                                 operand *result, iCode *ic)
11234 {
11235   //sym_link *retype = getSpec(operandType(result));
11236   // symbol *albl = newiTempLabel(NULL);        // patch 15
11237   // symbol *blbl = newiTempLabel(NULL);        //
11238   // PIC_OPCODE poc;                            // patch 15
11239   int size;
11240   int offset = 0;
11241
11242   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11243   pic16_aopOp(left,ic,FALSE);
11244   pic16_aopOp(result,ic,TRUE);
11245   size = AOP_SIZE(result);
11246
11247   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
11248
11249   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
11250
11251   // set up table pointer
11252   if( (AOP_TYPE(left) == AOP_PCODE) 
11253       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
11254           || (AOP(left)->aopu.pcop->type == PO_DIR)))
11255     {
11256       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
11257       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
11258       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
11259       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
11260       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
11261       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
11262   } else {
11263     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(left), 0);
11264     mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(left), 1);
11265     mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(left), 2);
11266   }
11267
11268   while(size--) {
11269     pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
11270     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
11271     offset++;
11272   }
11273     
11274   pic16_freeAsmop(left,NULL,ic,TRUE);
11275   pic16_freeAsmop(result,NULL,ic,TRUE);
11276 }
11277
11278
11279 /*-----------------------------------------------------------------*/
11280 /* genPointerGet - generate code for pointer get                   */
11281 /*-----------------------------------------------------------------*/
11282 static void genPointerGet (iCode *ic)
11283 {
11284   operand *left, *result ;
11285   sym_link *type, *etype;
11286   int p_type;
11287
11288     FENTRY;
11289     
11290     left = IC_LEFT(ic);
11291     result = IC_RESULT(ic) ;
11292
11293     /* depending on the type of pointer we need to
11294     move it to the correct pointer register */
11295     type = operandType(left);
11296     etype = getSpec(type);
11297
11298 #if 0
11299     if (IS_PTR_CONST(type))
11300 #else
11301     if (IS_CODEPTR(type))
11302 #endif
11303       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
11304
11305     /* if left is of type of pointer then it is simple */
11306     if (IS_PTR(type) && !IS_FUNC(type->next)) 
11307       p_type = DCL_TYPE(type);
11308     else {
11309       /* we have to go by the storage class */
11310       p_type = PTR_TYPE(SPEC_OCLS(etype));
11311
11312       DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
11313
11314       if (SPEC_OCLS(etype)->codesp ) {
11315         DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
11316         //p_type = CPOINTER ;   
11317       } else
11318       if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) {
11319         DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
11320         /*p_type = FPOINTER ;*/ 
11321       } else
11322       if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) {
11323         DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
11324         /* p_type = PPOINTER; */
11325       } else
11326       if (SPEC_OCLS(etype) == idata ) {
11327         DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
11328         /* p_type = IPOINTER; */
11329       } else {
11330         DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
11331         /* p_type = POINTER ; */
11332       }
11333     }
11334
11335     /* now that we have the pointer type we assign
11336     the pointer values */
11337     switch (p_type) {
11338       case POINTER:     
11339       case FPOINTER:
11340       case IPOINTER:
11341         genNearPointerGet (left,result,ic);
11342         break;
11343
11344       case PPOINTER:
11345         genPagedPointerGet(left,result,ic);
11346         break;
11347
11348 #if 0
11349       /* PICs do not support FAR pointers... */
11350       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
11351       case FPOINTER:
11352         genFarPointerGet (left,result,ic);
11353         break;
11354 #endif
11355
11356       case CPOINTER:
11357         genConstPointerGet (left,result,ic);
11358         //pic16_emitcodePointerGet (left,result,ic);
11359         break;
11360
11361       case GPOINTER:
11362 #if 0
11363       if (IS_PTR_CONST(type))
11364         genConstPointerGet (left,result,ic);
11365       else
11366 #endif
11367         genGenPointerGet (left,result,ic);
11368       break;
11369
11370     default:
11371       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
11372               "genPointerGet: illegal pointer type");
11373     
11374     }
11375 }
11376
11377 /*-----------------------------------------------------------------*/
11378 /* genPackBits - generates code for packed bit storage             */
11379 /*-----------------------------------------------------------------*/
11380 static void genPackBits (sym_link    *etype , operand *result,
11381                          operand *right ,
11382                          char *rname, int p_type)
11383 {
11384   int shCnt = 0 ;
11385   int offset = 0  ;
11386   int rLen = 0 ;
11387   int blen, bstr ;   
11388   int shifted_and_masked = 0;
11389   unsigned long lit = (unsigned long)-1;
11390   sym_link *retype;
11391
11392   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11393   blen = SPEC_BLEN(etype);
11394   bstr = SPEC_BSTR(etype);
11395
11396   retype = getSpec(operandType(right));
11397
11398   if(AOP_TYPE(right) == AOP_LIT) {
11399     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
11400     
11401     if((blen == 1) && (bstr < 8)) {
11402       /* it is a single bit, so use the appropriate bit instructions */
11403
11404       DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
11405
11406       if(!IS_PTR(operandType(result)) || IS_DIRECT(result)) {
11407         /* workaround to reduce the extra lfsr instruction */
11408         if(lit) {
11409           pic16_emitpcode(POC_BSF,
11410               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11411         } else {
11412           pic16_emitpcode(POC_BCF,
11413               pic16_popCopyGPR2Bit(pic16_popGet(AOP(result), 0), bstr));
11414         }
11415       } else {
11416         if (PIC_IS_DATA_PTR(operandType(result))) {
11417           pic16_loadFSR0(result, 0);
11418           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11419               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
11420         } else {
11421           /* get old value */
11422           pic16_derefPtr (result, p_type, 0, NULL);
11423           pic16_emitpcode(lit ? POC_BSF : POC_BCF,
11424               pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11425           /* write back new value */
11426           pic16_derefPtr (result, p_type, 1, NULL);
11427         }
11428       }
11429
11430       return;
11431     }
11432     /* IORLW below is more efficient */
11433     //pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & ((1UL << blen) - 1)) << bstr));
11434     lit = (lit & ((1UL << blen) - 1)) << bstr;
11435     shifted_and_masked = 1;
11436     offset++;
11437   } else
11438     if (IS_DIRECT(result) && !IS_PTR(operandType(result))
11439         && IS_BITFIELD(retype) 
11440         && (AOP_TYPE(right) == AOP_REG || AOP_TYPE(right) == AOP_DIR)
11441         && (blen == 1)) {
11442       int rblen, rbstr;
11443
11444       rblen = SPEC_BLEN( retype );
11445       rbstr = SPEC_BSTR( retype );
11446
11447       if(IS_BITFIELD(etype)) {
11448         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 0));
11449         pic16_emitpcode(POC_BCF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11450       } else {
11451         pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
11452       }
11453
11454       pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), 0), rbstr));
11455
11456       if(IS_BITFIELD(etype)) {
11457         pic16_emitpcode(POC_BSF, pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_wreg), bstr));
11458       } else {
11459         pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_wreg));
11460       }
11461
11462       pic16_emitpcode(POC_MOVWF, pic16_popGet( AOP(result), 0));
11463
11464       return;
11465     } else {
11466       /* move right to W */
11467       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
11468     }
11469
11470   /* if the bit length is less than or   */
11471   /* it exactly fits a byte then         */
11472   if((shCnt=SPEC_BSTR(etype))
11473       || SPEC_BLEN(etype) <= 8 )  {
11474     int fsr0_setup = 0;
11475
11476     if (blen != 8 || bstr != 0) {
11477       // we need to combine the value with the old value
11478       if(!shifted_and_masked)
11479       {
11480         pic16_emitpcode(POC_ANDLW, pic16_popGetLit((1U << blen)-1));
11481
11482         DEBUGpic16_emitcode(";", "shCnt = %d SPEC_BSTR(etype) = %d:%d", shCnt,
11483             SPEC_BSTR(etype), SPEC_BLEN(etype));
11484
11485         /* shift left acc, do NOT mask the result again */
11486         AccLsh(shCnt, 0);
11487
11488         /* using PRODH as a temporary register here */
11489         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodh));
11490       }
11491
11492       if ((IS_SYMOP(result) && !IS_PTR(operandType (result)))
11493         || IS_DIRECT(result)) {
11494         /* access symbol directly */
11495         pic16_mov2w (AOP(result), 0);
11496       } else {
11497         /* get old value */
11498         pic16_derefPtr (result, p_type, 0, &fsr0_setup);
11499       }
11500 #if 1
11501       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
11502             (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
11503                             (unsigned char)(0xff >> (8-bstr))) ));
11504       if (!shifted_and_masked) {
11505         pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11506       } else {
11507         /* We have the shifted and masked (literal) right value in `lit' */
11508         if (lit != 0)
11509           pic16_emitpcode(POC_IORLW, pic16_popGetLit(lit));
11510       }
11511     } // if (blen != 8 || bstr != 0)
11512
11513     /* write new value back */
11514     if ((IS_SYMOP(result) && !IS_PTR(operandType(result)))
11515         || IS_DIRECT(result)) {
11516       pic16_emitpcode (POC_MOVWF, pic16_popGet(AOP(result),0));
11517     } else {
11518       pic16_derefPtr (result, p_type, 1, &fsr0_setup);
11519     }
11520 #endif
11521
11522     return;
11523   }
11524
11525
11526 #if 0
11527   fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
11528   fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
11529   exit(EXIT_FAILURE);
11530 #endif
11531
11532
11533   pic16_loadFSR0(result, 0);                    // load FSR0 with address of result
11534   rLen = SPEC_BLEN(etype)-8;
11535
11536   /* now generate for lengths greater than one byte */
11537   while (1) {
11538     rLen -= 8 ;
11539     if (rLen <= 0 ) {
11540       mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), offset);
11541       break ;
11542     }
11543
11544     switch (p_type) {
11545       case POINTER:
11546         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11547         break;
11548
11549         /*
11550            case FPOINTER:
11551            MOVA(l);
11552            pic16_emitcode("movx","@dptr,a");
11553            break;
11554
11555            case GPOINTER:
11556            MOVA(l);
11557            DEBUGpic16_emitcode(";lcall","__gptrput");
11558            break;  
11559          */
11560       default:
11561         assert(0);
11562     }   
11563
11564
11565     pic16_mov2w(AOP(right), offset++);
11566   }
11567
11568   /* last last was not complete */
11569   if (rLen)   {
11570     /* save the byte & read byte */
11571     switch (p_type) {
11572       case POINTER:
11573         //                pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
11574         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
11575         break;
11576
11577         /*
11578            case FPOINTER:
11579            pic16_emitcode ("mov","b,a");
11580            pic16_emitcode("movx","a,@dptr");
11581            break;
11582
11583            case GPOINTER:
11584            pic16_emitcode ("push","b");
11585            pic16_emitcode ("push","acc");
11586            pic16_emitcode ("lcall","__gptrget");
11587            pic16_emitcode ("pop","b");
11588            break;
11589          */
11590       default:
11591         assert(0);
11592     }
11593     DEBUGpic16_emitcode(";", "rLen = %i", rLen);
11594     pic16_emitpcode(POC_ANDLW, pic16_popGetLit((unsigned char)-1 << -rLen));
11595     pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodh));
11596     //        pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
11597     //        pic16_emitcode ("orl","a,b");
11598   }
11599
11600   //    if (p_type == GPOINTER)
11601   //        pic16_emitcode("pop","b");
11602
11603   switch (p_type) {
11604
11605     case POINTER:
11606       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11607       //        pic16_emitcode("mov","@%s,a",rname);
11608       break;
11609       /*
11610          case FPOINTER:
11611          pic16_emitcode("movx","@dptr,a");
11612          break;
11613
11614          case GPOINTER:
11615          DEBUGpic16_emitcode(";lcall","__gptrput");
11616          break;                 
11617        */
11618     default:
11619       assert(0);
11620   }
11621
11622   //    pic16_freeAsmop(right, NULL, ic, TRUE);
11623 }
11624
11625 /*-----------------------------------------------------------------*/
11626 /* genDataPointerSet - remat pointer to data space                 */
11627 /*-----------------------------------------------------------------*/
11628 static void genDataPointerSet(operand *right,
11629                               operand *result,
11630                               iCode *ic)
11631 {
11632   int size, offset = 0, resoffset=0 ;
11633
11634     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11635     pic16_aopOp(right,ic,FALSE);
11636
11637     size = AOP_SIZE(right);
11638
11639 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
11640
11641 #if 0
11642     if ( AOP_TYPE(result) == AOP_PCODE) {
11643       fprintf(stderr,"genDataPointerSet   %s, %d\n",
11644               AOP(result)->aopu.pcop->name,
11645                 (AOP(result)->aopu.pcop->type == PO_DIR)?
11646               PCOR(AOP(result)->aopu.pcop)->instance:
11647               PCOI(AOP(result)->aopu.pcop)->offset);
11648     }
11649 #endif
11650
11651     if(AOP(result)->aopu.pcop->type == PO_DIR)
11652       resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
11653
11654     while (size--) {
11655       if (AOP_TYPE(right) == AOP_LIT) {
11656         unsigned int lit;
11657
11658           if(!IS_FLOAT(operandType( right )))
11659             lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11660           else {
11661             union {
11662               unsigned long lit_int;
11663               float lit_float;
11664             } info;
11665         
11666               /* take care if literal is a float */
11667               info.lit_float = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
11668               lit = info.lit_int;
11669           }
11670                     lit = lit >> (8*offset);
11671                     pic16_movLit2f(pic16_popGet(AOP(result),offset), lit);
11672                 } else {
11673                   pic16_mov2w(AOP(right), offset);
11674                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
11675                 }
11676                 offset++;
11677                 resoffset++;
11678         }
11679
11680     pic16_freeAsmop(right,NULL,ic,TRUE);
11681 }
11682
11683
11684
11685 /*-----------------------------------------------------------------*/
11686 /* genNearPointerSet - pic16_emitcode for near pointer put         */
11687 /*-----------------------------------------------------------------*/
11688 static void genNearPointerSet (operand *right,
11689                                operand *result, 
11690                                iCode *ic)
11691 {
11692   asmop *aop = NULL;
11693   sym_link *retype;
11694   sym_link *ptype = operandType(result);
11695   sym_link *resetype;
11696     
11697     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11698     retype= getSpec(operandType(right));
11699     resetype = getSpec(operandType(result));
11700   
11701     pic16_aopOp(result,ic,FALSE);
11702     
11703     /* if the result is rematerializable &
11704      * in data space & not a bit variable */
11705         
11706     /* and result is not a bit variable */
11707     if (AOP_TYPE(result) == AOP_PCODE
11708 //      && AOP_TYPE(result) == AOP_IMMD
11709       && DCL_TYPE(ptype) == POINTER
11710       && !IS_BITFIELD(retype)
11711       && !IS_BITFIELD(resetype)) {
11712
11713         genDataPointerSet (right,result,ic);
11714         pic16_freeAsmop(result,NULL,ic,TRUE);
11715       return;
11716     }
11717
11718     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11719     pic16_aopOp(right,ic,FALSE);
11720     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11721
11722     /* if bitfield then unpack the bits */
11723     if (IS_BITFIELD(resetype)) {
11724       genPackBits (resetype, result, right, NULL, POINTER);
11725     } else {
11726       /* we have can just get the values */
11727       int size = AOP_SIZE(right);
11728       int offset = 0 ;    
11729
11730         pic16_loadFSR0(result, 0);
11731             
11732         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11733         while (size--) {
11734           if (AOP_TYPE(right) == AOP_LIT) {
11735             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11736             if (size) {
11737               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
11738             } else {
11739               pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
11740             }
11741           } else { // no literal
11742             if(size) {
11743               pic16_emitpcode(POC_MOVFF,
11744                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11745                   pic16_popCopyReg(&pic16_pc_postinc0)));
11746             } else {
11747               pic16_emitpcode(POC_MOVFF,
11748                   pic16_popGet2p(pic16_popGet(AOP(right),offset),
11749                   pic16_popCopyReg(&pic16_pc_indf0)));
11750             }
11751           }
11752           
11753           offset++;
11754         }
11755     }
11756
11757     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11758     /* now some housekeeping stuff */
11759     if (aop) {
11760       /* we had to allocate for this iCode */
11761       pic16_freeAsmop(NULL,aop,ic,TRUE);
11762     } else { 
11763       /* we did not allocate which means left
11764        * already in a pointer register, then
11765        * if size > 0 && this could be used again
11766        * we have to point it back to where it 
11767        * belongs */
11768       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11769       if (AOP_SIZE(right) > 1
11770         && !OP_SYMBOL(result)->remat
11771         && ( OP_SYMBOL(result)->liveTo > ic->seq
11772         || ic->depth )) {
11773
11774           int size = AOP_SIZE(right) - 1;
11775
11776             while (size--)
11777               pic16_emitcode("decf","fsr0,f");
11778               //pic16_emitcode("dec","%s",rname);
11779       }
11780     }
11781
11782     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11783     /* done */
11784 //release:
11785     pic16_freeAsmop(right,NULL,ic,TRUE);
11786     pic16_freeAsmop(result,NULL,ic,TRUE);
11787 }
11788
11789 /*-----------------------------------------------------------------*/
11790 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
11791 /*-----------------------------------------------------------------*/
11792 static void genPagedPointerSet (operand *right,
11793                                operand *result, 
11794                                iCode *ic)
11795 {
11796     asmop *aop = NULL;
11797     regs *preg = NULL ;
11798     char *rname , *l;
11799     sym_link *retype;
11800        
11801     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11802
11803     retype= getSpec(operandType(right));
11804     
11805     pic16_aopOp(result,ic,FALSE);
11806     
11807     /* if the value is already in a pointer register
11808        then don't need anything more */
11809     if (!AOP_INPREG(AOP(result))) {
11810         /* otherwise get a free pointer register */
11811         aop = newAsmop(0);
11812         preg = getFreePtr(ic,&aop,FALSE);
11813         pic16_emitcode("mov","%s,%s",
11814                 preg->name,
11815                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
11816         rname = preg->name ;
11817     } else
11818         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11819     
11820     pic16_freeAsmop(result,NULL,ic,TRUE);
11821     pic16_aopOp (right,ic,FALSE);
11822
11823     /* if bitfield then unpack the bits */
11824     if (IS_BITFIELD(retype)) 
11825         genPackBits (retype,result,right,rname,PPOINTER);
11826     else {
11827         /* we have can just get the values */
11828         int size = AOP_SIZE(right);
11829         int offset = 0 ;        
11830         
11831         while (size--) {
11832             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
11833             
11834             MOVA(l);
11835             pic16_emitcode("movx","@%s,a",rname);
11836
11837             if (size)
11838                 pic16_emitcode("inc","%s",rname);
11839
11840             offset++;
11841         }
11842     }
11843     
11844     /* now some housekeeping stuff */
11845     if (aop) {
11846         /* we had to allocate for this iCode */
11847         pic16_freeAsmop(NULL,aop,ic,TRUE);
11848     } else { 
11849         /* we did not allocate which means left
11850            already in a pointer register, then
11851            if size > 0 && this could be used again
11852            we have to point it back to where it 
11853            belongs */
11854         if (AOP_SIZE(right) > 1 &&
11855             !OP_SYMBOL(result)->remat &&
11856             ( OP_SYMBOL(result)->liveTo > ic->seq ||
11857               ic->depth )) {
11858             int size = AOP_SIZE(right) - 1;
11859             while (size--)
11860                 pic16_emitcode("dec","%s",rname);
11861         }
11862     }
11863
11864     /* done */
11865     pic16_freeAsmop(right,NULL,ic,TRUE);
11866     
11867         
11868 }
11869
11870 #if 0
11871 /* This code is not adjusted to PIC16 and fails utterly...
11872  * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */
11873
11874 /*-----------------------------------------------------------------*/
11875 /* genFarPointerSet - set value from far space                     */
11876 /*-----------------------------------------------------------------*/
11877 static void genFarPointerSet (operand *right,
11878                               operand *result, iCode *ic)
11879 {
11880     int size, offset ;
11881     sym_link *retype = getSpec(operandType(right));
11882
11883     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11884     pic16_aopOp(result,ic,FALSE);
11885
11886     /* if the operand is already in dptr 
11887     then we do nothing else we move the value to dptr */
11888     if (AOP_TYPE(result) != AOP_STR) {
11889         /* if this is remateriazable */
11890         if (AOP_TYPE(result) == AOP_IMMD)
11891             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
11892         else { /* we need to get it byte by byte */
11893             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
11894             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
11895             if (options.model == MODEL_FLAT24)
11896             {
11897                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
11898             }
11899         }
11900     }
11901     /* so dptr know contains the address */
11902     pic16_freeAsmop(result,NULL,ic,TRUE);
11903     pic16_aopOp(right,ic,FALSE);
11904
11905     /* if bit then unpack */
11906     if (IS_BITFIELD(retype)) 
11907         genPackBits(retype,result,right,"dptr",FPOINTER);
11908     else {
11909         size = AOP_SIZE(right);
11910         offset = 0 ;
11911
11912         while (size--) {
11913             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
11914             MOVA(l);
11915             pic16_emitcode("movx","@dptr,a");
11916             if (size)
11917                 pic16_emitcode("inc","dptr");
11918         }
11919     }
11920
11921     pic16_freeAsmop(right,NULL,ic,TRUE);
11922 }
11923 #endif
11924
11925 /*-----------------------------------------------------------------*/
11926 /* genGenPointerSet - set value from generic pointer space         */
11927 /*-----------------------------------------------------------------*/
11928 #if 0
11929 static void genGenPointerSet (operand *right,
11930                               operand *result, iCode *ic)
11931 {
11932         int i, size, offset, lit;
11933         sym_link *retype = getSpec(operandType(right));
11934
11935         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11936
11937         pic16_aopOp(result,ic,FALSE);
11938         pic16_aopOp(right,ic,FALSE);
11939         size = AOP_SIZE(right);
11940         offset = 0;
11941
11942         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
11943
11944         /* if the operand is already in dptr 
11945                 then we do nothing else we move the value to dptr */
11946         if (AOP_TYPE(result) != AOP_STR) {
11947                 /* if this is remateriazable */
11948                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11949                 // WARNING: anythig until "else" is untested!
11950                 if (AOP_TYPE(result) == AOP_IMMD) {
11951                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11952                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
11953                         // load FSR0 from immediate
11954                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
11955                         offset = 0;
11956                         while(size--) {
11957                                 if(size) {
11958                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
11959                                 } else {
11960                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
11961                                 }
11962                                 offset++;
11963                         }
11964                         goto release;
11965                 }
11966                 else { /* we need to get it byte by byte */
11967                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11968                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
11969
11970                         // set up FSR0 with address of result
11971                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
11972                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
11973
11974                         /* hack hack! see if this the FSR. If so don't load W */
11975                         if(AOP_TYPE(right) != AOP_ACC) {
11976
11977                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11978
11979                                 if(AOP_TYPE(right) == AOP_LIT)
11980                                 {
11981                                         // copy literal
11982                                         // note: pic16_popGet handles sign extension
11983                                         for(i=0;i<size;i++) {
11984                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
11985                                                 if(i < size-1)
11986                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
11987                                                 else
11988                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
11989                                         }
11990                                 } else {
11991                                         // copy regs
11992
11993                                         for(i=0;i<size;i++) {
11994                                                 if(i < size-1)
11995                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11996                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
11997                                                 else
11998                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
11999                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
12000                                         }
12001                                 }
12002                                 goto release;
12003                         } 
12004                         // right = ACC
12005                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12006                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12007                         goto release;
12008         } // if (AOP_TYPE(result) != AOP_IMMD)
12009
12010         } // if (AOP_TYPE(result) != AOP_STR)
12011         /* so dptr know contains the address */
12012
12013
12014         /* if bit then unpack */
12015         if (IS_BITFIELD(retype)) 
12016                 genPackBits(retype,result,right,"dptr",GPOINTER);
12017         else {
12018                 size = AOP_SIZE(right);
12019                 offset = 0 ;
12020
12021                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12022
12023                 // set up FSR0 with address of result
12024                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
12025                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
12026         
12027                 while (size--) {
12028                         if (AOP_TYPE(right) == AOP_LIT) {
12029                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12030                                 if (size) {
12031                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
12032                                 } else {
12033                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
12034                                 }
12035                         } else { // no literal
12036                                 if(size) {
12037                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
12038                                 } else {
12039                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
12040                                 }
12041                         }
12042                         offset++;
12043                 }
12044         }
12045
12046         release:
12047         pic16_freeAsmop(right,NULL,ic,TRUE);
12048         pic16_freeAsmop(result,NULL,ic,TRUE);
12049 }
12050 #endif
12051
12052 static void genGenPointerSet (operand *right,
12053                               operand *result, iCode *ic)
12054 {
12055   int size;
12056   sym_link *retype = getSpec(operandType(result));
12057
12058     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12059
12060     pic16_aopOp(result,ic,FALSE);
12061     pic16_aopOp(right,ic,FALSE);
12062     size = AOP_SIZE(right);
12063
12064     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12065
12066
12067     /* if bit then unpack */
12068     if (IS_BITFIELD(retype)) {
12069 //      pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
12070       genPackBits(retype,result,right,"dptr",GPOINTER);
12071       goto release;
12072     }
12073
12074     size = AOP_SIZE(right);
12075
12076     DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
12077
12078
12079     /* load value to write in TBLPTRH:TBLPTRL:PRODH:[stack] */
12080
12081     /* value of right+0 is placed on stack, which will be retrieved
12082      * by the support function thus restoring the stack. The important
12083      * thing is that there is no need to manually restore stack pointer
12084      * here */
12085     pushaop(AOP(right), 0);
12086 //    mov2fp(pic16_popCopyReg(&pic16_pc_postdec1), AOP(right), 0);
12087     if(size>1)mov2fp(pic16_popCopyReg(&pic16_pc_prodh), AOP(right), 1);
12088     if(size>2)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(right), 2);
12089     if(size>3)mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(right), 3);
12090     
12091     /* load address to write to in WREG:FSR0H:FSR0L */
12092     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 0),
12093                                 pic16_popCopyReg(&pic16_pc_fsr0l)));
12094     pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result), 1),
12095                                 pic16_popCopyReg(&pic16_pc_prodl)));
12096     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result), 2));
12097     
12098     pic16_callGenericPointerRW(1, size);
12099
12100 release:
12101     pic16_freeAsmop(right,NULL,ic,TRUE);
12102     pic16_freeAsmop(result,NULL,ic,TRUE);
12103 }
12104
12105 /*-----------------------------------------------------------------*/
12106 /* genPointerSet - stores the value into a pointer location        */
12107 /*-----------------------------------------------------------------*/
12108 static void genPointerSet (iCode *ic)
12109 {    
12110   operand *right, *result ;
12111   sym_link *type, *etype;
12112   int p_type;
12113
12114     FENTRY;
12115
12116     right = IC_RIGHT(ic);
12117     result = IC_RESULT(ic) ;
12118
12119     /* depending on the type of pointer we need to
12120     move it to the correct pointer register */
12121     type = operandType(result);
12122     etype = getSpec(type);
12123     
12124     /* if left is of type of pointer then it is simple */
12125     if (IS_PTR(type) && !IS_FUNC(type->next)) {
12126         p_type = DCL_TYPE(type);
12127     }
12128     else {
12129         /* we have to go by the storage class */
12130         p_type = PTR_TYPE(SPEC_OCLS(etype));
12131
12132 /*      if (SPEC_OCLS(etype)->codesp ) { */
12133 /*          p_type = CPOINTER ;  */
12134 /*      } */
12135 /*      else */
12136 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
12137 /*              p_type = FPOINTER ; */
12138 /*          else */
12139 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
12140 /*                  p_type = PPOINTER ; */
12141 /*              else */
12142 /*                  if (SPEC_OCLS(etype) == idata ) */
12143 /*                      p_type = IPOINTER ; */
12144 /*                  else */
12145 /*                      p_type = POINTER ; */
12146     }
12147
12148     /* now that we have the pointer type we assign
12149     the pointer values */
12150     switch (p_type) {
12151       case POINTER:
12152       case FPOINTER:
12153       case IPOINTER:
12154         genNearPointerSet (right,result,ic);
12155         break;
12156
12157       case PPOINTER:
12158         genPagedPointerSet (right,result,ic);
12159         break;
12160
12161 #if 0
12162       /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */
12163       case FPOINTER:
12164         genFarPointerSet (right,result,ic);
12165         break;
12166 #endif
12167         
12168       case GPOINTER:
12169         genGenPointerSet (right,result,ic);
12170         break;
12171
12172       default:
12173         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
12174           "genPointerSet: illegal pointer type");
12175     }
12176 }
12177
12178 /*-----------------------------------------------------------------*/
12179 /* genIfx - generate code for Ifx statement                        */
12180 /*-----------------------------------------------------------------*/
12181 static void genIfx (iCode *ic, iCode *popIc)
12182 {
12183   operand *cond = IC_COND(ic);
12184   int isbit =0;
12185
12186     FENTRY;
12187
12188     pic16_aopOp(cond,ic,FALSE);
12189
12190     /* get the value into acc */
12191     if (AOP_TYPE(cond) != AOP_CRY)
12192       pic16_toBoolean(cond);
12193     else
12194       isbit = 1;
12195     /* the result is now in the accumulator */
12196     pic16_freeAsmop(cond,NULL,ic,TRUE);
12197
12198     /* if there was something to be popped then do it */
12199     if (popIc)
12200       genIpop(popIc);
12201
12202     /* if the condition is  a bit variable */
12203     if (isbit && IS_ITEMP(cond) && 
12204         SPIL_LOC(cond)) {
12205       genIfxJump(ic,"c");
12206       DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
12207     } else {
12208       if (isbit && !IS_ITEMP(cond))
12209         genIfxJump(ic,OP_SYMBOL(cond)->rname);
12210         else
12211         genIfxJump(ic,"a");
12212     }
12213     ic->generated = 1;
12214 }
12215
12216 /*-----------------------------------------------------------------*/
12217 /* genAddrOf - generates code for address of                       */
12218 /*-----------------------------------------------------------------*/
12219 static void genAddrOf (iCode *ic)
12220 {
12221   operand *result, *left;
12222   int size;
12223   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
12224   pCodeOp *pcop0, *pcop1, *pcop2;
12225
12226     FENTRY;
12227
12228     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
12229
12230     sym = OP_SYMBOL( IC_LEFT(ic) );
12231     
12232     if(sym->onStack) {
12233       /* get address of symbol on stack */
12234       DEBUGpic16_emitcode(";    ", "%s symbol %s on stack", __FUNCTION__, sym->name);
12235 #if 0
12236       fprintf(stderr, "%s:%d symbol %s on stack offset %i\n", __FILE__, __LINE__,
12237                   OP_SYMBOL(IC_LEFT(ic))->name, OP_SYMBOL(IC_LEFT(ic))->stack);
12238 #endif
12239
12240       // operands on stack are accessible via "FSR2 + index" with index
12241       // starting at 2 for arguments and growing from 0 downwards for
12242       // local variables (index == 0 is not assigned so we add one here)
12243       {
12244         int soffs = OP_SYMBOL( IC_LEFT(ic))->stack;
12245
12246           if (soffs <= 0) {
12247             assert (soffs < 0);
12248             soffs++;
12249           } // if
12250
12251           DEBUGpic16_emitcode("*!*", "accessing stack symbol at offset=%d", soffs);
12252           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( soffs & 0x00FF ));
12253           pic16_emitpcode(POC_ADDFW , pic16_popCopyReg(pic16_framepnt_lo));
12254           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 0));
12255           pic16_emitpcode(POC_MOVLW , pic16_popGetLit( (soffs >> 8) & 0x00FF ));
12256           pic16_emitpcode(POC_ADDFWC, pic16_popCopyReg(pic16_framepnt_hi));
12257           pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result), 1));
12258       }
12259
12260       goto release;
12261     }
12262         
12263 //      if(pic16_debug_verbose) {
12264 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
12265 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
12266 //      }
12267         
12268     pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
12269     size = AOP_SIZE(IC_RESULT(ic));
12270
12271     pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12272     pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12273     pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12274         
12275     if (size == 3) {
12276       pic16_emitpcode(POC_MOVLW, pcop0);
12277       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
12278       pic16_emitpcode(POC_MOVLW, pcop1);
12279       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
12280       pic16_emitpcode(POC_MOVLW, pcop2);
12281       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
12282     } else
12283     if (size == 2) {
12284       pic16_emitpcode(POC_MOVLW, pcop0);
12285       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12286       pic16_emitpcode(POC_MOVLW, pcop1);
12287     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
12288     } else {
12289       pic16_emitpcode(POC_MOVLW, pcop0);
12290       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
12291     }
12292
12293     pic16_freeAsmop(left, NULL, ic, FALSE);
12294 release:
12295     pic16_freeAsmop(result,NULL,ic,TRUE);
12296 }
12297
12298
12299 #if 0
12300 /*-----------------------------------------------------------------*/
12301 /* genFarFarAssign - assignment when both are in far space         */
12302 /*-----------------------------------------------------------------*/
12303 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
12304 {
12305     int size = AOP_SIZE(right);
12306     int offset = 0;
12307     char *l ;
12308     /* first push the right side on to the stack */
12309     while (size--) {
12310         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
12311         MOVA(l);
12312         pic16_emitcode ("push","acc");
12313     }
12314     
12315     pic16_freeAsmop(right,NULL,ic,FALSE);
12316     /* now assign DPTR to result */
12317     pic16_aopOp(result,ic,FALSE);
12318     size = AOP_SIZE(result);
12319     while (size--) {
12320         pic16_emitcode ("pop","acc");
12321         pic16_aopPut(AOP(result),"a",--offset);
12322     }
12323     pic16_freeAsmop(result,NULL,ic,FALSE);
12324         
12325 }
12326 #endif
12327
12328 /*-----------------------------------------------------------------*/
12329 /* genAssign - generate code for assignment                        */
12330 /*-----------------------------------------------------------------*/
12331 static void genAssign (iCode *ic)
12332 {
12333   operand *result, *right;
12334   sym_link *restype, *rtype;
12335   int size, offset,know_W;
12336   unsigned long lit = 0L;
12337
12338     result = IC_RESULT(ic);
12339     right  = IC_RIGHT(ic) ;
12340
12341     FENTRY;
12342   
12343     /* if they are the same */
12344     if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
12345       return ;
12346
12347     /* reversed order operands are aopOp'ed so that result operand
12348      * is effective in case right is a stack symbol. This maneauver
12349      * allows to use the _G.resDirect flag later */
12350      pic16_aopOp(result,ic,TRUE);
12351     pic16_aopOp(right,ic,FALSE);
12352
12353     DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12354
12355     /* if they are the same registers */
12356     if (pic16_sameRegs(AOP(right),AOP(result)))
12357       goto release;
12358
12359     /* if the result is a bit */
12360     if (AOP_TYPE(result) == AOP_CRY) {
12361       /* if the right size is a literal then
12362          we know what the value is */
12363       if (AOP_TYPE(right) == AOP_LIT) {
12364           
12365         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12366             pic16_popGet(AOP(result),0));
12367
12368         if (((int) operandLitValue(right))) 
12369           pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
12370               AOP(result)->aopu.aop_dir,
12371               AOP(result)->aopu.aop_dir);
12372         else
12373           pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
12374               AOP(result)->aopu.aop_dir,
12375               AOP(result)->aopu.aop_dir);
12376         
12377         goto release;
12378       }
12379
12380       /* the right is also a bit variable */
12381       if (AOP_TYPE(right) == AOP_CRY) {
12382         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12383         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12384         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12385
12386         goto release ;
12387       }
12388
12389       /* we need to or */
12390       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12391       pic16_toBoolean(right);
12392       emitSKPZ;
12393       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12394       //pic16_aopPut(AOP(result),"a",0);
12395       goto release ;
12396     }
12397
12398     /* bit variables done */
12399     /* general case */
12400     size = AOP_SIZE(result);
12401     offset = 0 ;
12402
12403   /* bit variables done */
12404   /* general case */
12405   size = AOP_SIZE(result);
12406   restype = operandType(result);
12407   rtype = operandType(right);
12408   offset = 0 ;
12409
12410   if(AOP_TYPE(right) == AOP_LIT) {
12411     if(!(IS_FLOAT(operandType( right )) || IS_FIXED(operandType(right))))
12412     {
12413       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
12414
12415       /* patch tag for literals that are cast to pointers */
12416       if (IS_CODEPTR(restype)) {
12417         //fprintf (stderr, "%s:%u: INFO: `(__code*)literal'\n", ic->filename, ic->lineno);
12418         lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12419       } else {
12420         if (IS_GENPTR(restype))
12421         {
12422           if (IS_CODEPTR(rtype)) {
12423             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __code*)'\n", ic->filename, ic->lineno);
12424             lit = (lit & 0x00ffff) | (GPTR_TAG_CODE << 16);
12425           } else if (PIC_IS_DATA_PTR(rtype)) {
12426             //fprintf (stderr, "%s:%u: INFO: `(generic*)(literal __data*)'\n", ic->filename, ic->lineno);
12427             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12428           } else if (!IS_PTR(rtype) || IS_GENPTR(rtype)) {
12429             //fprintf (stderr, "%s:%u: INFO: `(generic*)literal' -- accepting specified tag %02x\n", ic->filename, ic->lineno, (unsigned char)(lit >> 16));
12430           } else if (IS_PTR(rtype)) {
12431             fprintf (stderr, "%s:%u: WARNING: `(generic*)literal' -- assuming __data space\n", ic->filename, ic->lineno);
12432             lit = (lit & 0x00ffff) | (GPTR_TAG_DATA << 16);
12433           }
12434         }
12435       }
12436     } else {
12437       union {
12438         unsigned long lit_int;
12439         float lit_float;
12440       } info;
12441
12442
12443       if(IS_FIXED16X16(operandType(right))) {
12444         lit = (unsigned long)fixed16x16FromDouble( floatFromVal( AOP(right)->aopu.aop_lit));
12445       } else {
12446         /* take care if literal is a float */
12447         info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
12448         lit = info.lit_int;
12449       }
12450     }
12451   }
12452
12453 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
12454 //                      sizeof(unsigned long int), sizeof(float));
12455
12456
12457     if (AOP_TYPE(right) == AOP_REG) {
12458       DEBUGpic16_emitcode(";   ", "%s:%d assign from register\n", __FUNCTION__, __LINE__);
12459       while (size--) {
12460         pic16_emitpcode (POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset++));
12461       } // while
12462       goto release;
12463     }
12464
12465     /* when do we have to read the program memory?
12466      * - if right itself is a symbol in code space
12467      *   (we don't care what it points to if it's a pointer)
12468      * - AND right is not a function (we would want its address)
12469      */
12470     if(AOP_TYPE(right) != AOP_LIT
12471       && IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(right)))
12472       && !IS_FUNC(OP_SYM_TYPE(right))
12473       && !IS_ITEMP(right)) {
12474
12475       DEBUGpic16_emitcode(";   ", "%s:%d symbol in code space, take special care\n", __FUNCTION__, __LINE__);
12476       fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name);
12477       
12478       // set up table pointer
12479       if(is_LitOp(right)) {
12480 //      fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__);
12481         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0));
12482         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
12483         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),1));
12484         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
12485         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),2));
12486         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
12487       } else {
12488 //      fprintf(stderr, "%s:%d inside block 2\n", __FILE__, __LINE__);
12489         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),0),
12490             pic16_popCopyReg(&pic16_pc_tblptrl)));
12491         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),1),
12492             pic16_popCopyReg(&pic16_pc_tblptrh)));
12493         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),2),
12494             pic16_popCopyReg(&pic16_pc_tblptru)));
12495       }
12496
12497       /* must fetch 3 bytes for pointers (was OP_SYM_ETYPE before) */
12498       size = min(getSize(OP_SYM_TYPE(right)), AOP_SIZE(result));
12499       while(size--) {
12500         pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
12501         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat),
12502             pic16_popGet(AOP(result),offset)));
12503         offset++;
12504       }
12505
12506       /* FIXME: for pointers we need to extend differently (according
12507        * to pointer type DATA/CODE/EEPROM/... :*/
12508       size = getSize(OP_SYM_TYPE(right));
12509       if(AOP_SIZE(result) > size) {
12510         size = AOP_SIZE(result) - size;
12511         while(size--) {
12512           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offset));
12513           offset++;
12514         }
12515       }
12516       goto release;
12517     }
12518
12519 #if 0
12520     /* VR - What is this?! */
12521     if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
12522       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12523       
12524       if(aopIdx(AOP(result),0) == 4) {
12525         /* this is a workaround to save value of right into wreg too,
12526          * value of wreg is going to be used later */
12527         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12528         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
12529         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12530         goto release;
12531       } else
12532 //      assert(0);
12533       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
12534     }
12535 #endif
12536
12537   know_W=-1;
12538   while (size--) {
12539     DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
12540     if(AOP_TYPE(right) == AOP_LIT) {
12541       if(lit&0xff) {
12542         if(know_W != (lit&0xff))
12543           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
12544         know_W = lit&0xff;
12545         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12546       } else
12547         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12548
12549       lit >>= 8;
12550
12551     } else if (AOP_TYPE(right) == AOP_CRY) {
12552       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
12553       if(offset == 0) {
12554         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
12555         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
12556         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
12557       }
12558     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
12559         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
12560         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
12561     } else {
12562       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
12563
12564       if(!_G.resDirect) {                                               /* use this aopForSym feature */
12565           if(AOP_TYPE(result) == AOP_ACC) {
12566             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
12567           } else
12568           if(AOP_TYPE(right) == AOP_ACC) {
12569             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
12570           } else {
12571             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
12572           }
12573       }
12574     }
12575       
12576       offset++;
12577     }
12578   
12579 release:
12580   pic16_freeAsmop (right,NULL,ic,FALSE);
12581   pic16_freeAsmop (result,NULL,ic,TRUE);
12582
12583
12584 /*-----------------------------------------------------------------*/
12585 /* genJumpTab - generates code for jump table                       */
12586 /*-----------------------------------------------------------------*/
12587 static void genJumpTab (iCode *ic)
12588 {
12589   symbol *jtab;
12590   char *l;
12591   pCodeOp *jt_offs;
12592   pCodeOp *jt_offs_hi;
12593   pCodeOp *jt_label;
12594
12595     FENTRY;
12596
12597     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
12598     /* get the condition into accumulator */
12599     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
12600     MOVA(l);
12601     /* multiply by three */
12602     pic16_emitcode("add","a,acc");
12603     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
12604
12605     jtab = newiTempLabel(NULL);
12606     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
12607     pic16_emitcode("jmp","@a+dptr");
12608     pic16_emitcode("","%05d_DS_:",jtab->key+100);
12609
12610 #if 0
12611     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
12612     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
12613     emitSKPNC;
12614     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
12615     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
12616     pic16_emitpLabel(jtab->key);
12617
12618 #else
12619
12620     jt_offs = pic16_popGetTempReg(0);
12621     jt_offs_hi = pic16_popGetTempReg(1);
12622     jt_label = pic16_popGetLabel (jtab->key);
12623     //fprintf (stderr, "Creating jump table...\n");
12624
12625     // calculate offset into jump table (idx * sizeof (GOTO))
12626     pic16_emitpcode(POC_CLRF  , jt_offs_hi);
12627     pic16_emitpcode(POC_RLCFW , pic16_popGet(AOP(IC_JTCOND(ic)),0));
12628     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12629     pic16_emitpcode(POC_RLCFW , pic16_popCopyReg(&pic16_pc_wreg));
12630     pic16_emitpcode(POC_RLCF  , jt_offs_hi);
12631     pic16_emitpcode(POC_ANDLW , pic16_popGetLit (0xFC));
12632     pic16_emitpcode(POC_MOVWF , jt_offs);
12633
12634     // prepare PCLATx (set to first entry in jump table)
12635     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 2, 0));
12636     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclatu));
12637     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 1, 0));
12638     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pclath));
12639     pic16_emitpcode(POC_MOVLW , pic16_popGetImmd(jt_label->name, 0, 0));
12640
12641     // set PCLATx to selected entry (new PCL is stored in jt_offs)
12642     pic16_emitpcode(POC_ADDWF , jt_offs);
12643     pic16_emitpcode(POC_MOVFW , jt_offs_hi);
12644     pic16_emitpcode(POC_ADDWFC, pic16_popCopyReg(&pic16_pc_pclath));
12645     emitSKPNC;
12646     pic16_emitpcode(POC_INCF  , pic16_popCopyReg(&pic16_pc_pclatu));
12647
12648     // release temporaries and prepare jump into table (new PCL --> WREG)
12649     pic16_emitpcode(POC_MOVFW , jt_offs);
12650     pic16_popReleaseTempReg (jt_offs_hi, 1);
12651     pic16_popReleaseTempReg (jt_offs, 0);
12652
12653     // jump into the table
12654     pic16_emitpcode(POC_MOVWF , pic16_popCopyReg(&pic16_pc_pcl));
12655
12656     pic16_emitpLabelFORCE(jtab->key);
12657 #endif
12658
12659     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
12660 //          pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN));
12661
12662     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_BEGIN, ""));
12663     /* now generate the jump labels */
12664     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
12665          jtab = setNextItem(IC_JTLABELS(ic))) {
12666 //        pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
12667         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
12668         
12669     }
12670     pic16_emitpinfo (INF_OPTIMIZATION, pic16_newpCodeOpOpt (OPT_JUMPTABLE_END, ""));
12671
12672 }
12673
12674 /*-----------------------------------------------------------------*/
12675 /* genMixedOperation - gen code for operators between mixed types  */
12676 /*-----------------------------------------------------------------*/
12677 /*
12678   TSD - Written for the PIC port - but this unfortunately is buggy.
12679   This routine is good in that it is able to efficiently promote 
12680   types to different (larger) sizes. Unfortunately, the temporary
12681   variables that are optimized out by this routine are sometimes
12682   used in other places. So until I know how to really parse the 
12683   iCode tree, I'm going to not be using this routine :(.
12684 */
12685 static int genMixedOperation (iCode *ic)
12686 {
12687 #if 0
12688   operand *result = IC_RESULT(ic);
12689   sym_link *ctype = operandType(IC_LEFT(ic));
12690   operand *right = IC_RIGHT(ic);
12691   int ret = 0;
12692   int big,small;
12693   int offset;
12694
12695   iCode *nextic;
12696   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
12697
12698   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12699
12700   nextic = ic->next;
12701   if(!nextic)
12702     return 0;
12703
12704   nextright = IC_RIGHT(nextic);
12705   nextleft  = IC_LEFT(nextic);
12706   nextresult = IC_RESULT(nextic);
12707
12708   pic16_aopOp(right,ic,FALSE);
12709   pic16_aopOp(result,ic,FALSE);
12710   pic16_aopOp(nextright,  nextic, FALSE);
12711   pic16_aopOp(nextleft,   nextic, FALSE);
12712   pic16_aopOp(nextresult, nextic, FALSE);
12713
12714   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
12715
12716     operand *t = right;
12717     right = nextright;
12718     nextright = t; 
12719
12720     pic16_emitcode(";remove right +","");
12721
12722   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
12723 /*
12724     operand *t = right;
12725     right = nextleft;
12726     nextleft = t; 
12727 */
12728     pic16_emitcode(";remove left +","");
12729   } else
12730     return 0;
12731
12732   big = AOP_SIZE(nextleft);
12733   small = AOP_SIZE(nextright);
12734
12735   switch(nextic->op) {
12736
12737   case '+':
12738     pic16_emitcode(";optimize a +","");
12739     /* if unsigned or not an integral type */
12740     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
12741       pic16_emitcode(";add a bit to something","");
12742     } else {
12743
12744       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
12745
12746       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
12747         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
12748         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
12749       } else
12750         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
12751
12752       offset = 0;
12753       while(--big) {
12754
12755         offset++;
12756
12757         if(--small) {
12758           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12759             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12760             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12761           }
12762
12763           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12764           emitSKPNC;
12765           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12766                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
12767                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
12768           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12769           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
12770
12771         } else {
12772           pic16_emitcode("rlf","known_zero,w");
12773
12774           /*
12775             if right is signed
12776               btfsc  right,7
12777                addlw ff
12778           */
12779           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
12780             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
12781             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12782           } else {
12783             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
12784           }
12785         }
12786       }
12787       ret = 1;
12788     }
12789   }
12790   ret = 1;
12791
12792 release:
12793   pic16_freeAsmop(right,NULL,ic,TRUE);
12794   pic16_freeAsmop(result,NULL,ic,TRUE);
12795   pic16_freeAsmop(nextright,NULL,ic,TRUE);
12796   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
12797   if(ret)
12798     nextic->generated = 1;
12799
12800   return ret;
12801 #else
12802   return 0;
12803 #endif
12804 }
12805 /*-----------------------------------------------------------------*/
12806 /* genCast - gen code for casting                                  */
12807 /*-----------------------------------------------------------------*/
12808 static void genCast (iCode *ic)
12809 {
12810   operand *result = IC_RESULT(ic);
12811   sym_link *ctype = operandType(IC_LEFT(ic));
12812   sym_link *rtype = operandType(IC_RIGHT(ic));
12813   sym_link *restype = operandType(IC_RESULT(ic));
12814   operand *right = IC_RIGHT(ic);
12815   int size, offset ;
12816
12817
12818     FENTRY;
12819
12820         /* if they are equivalent then do nothing */
12821 //      if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
12822 //              return ;
12823
12824         pic16_aopOp(result,ic,FALSE);
12825         pic16_aopOp(right,ic,FALSE) ;
12826
12827         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
12828
12829
12830         /* if the result is a bit */
12831         if (AOP_TYPE(result) == AOP_CRY) {
12832         
12833                 /* if the right size is a literal then
12834                  * we know what the value is */
12835                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12836
12837                 if (AOP_TYPE(right) == AOP_LIT) {
12838                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
12839                                 pic16_popGet(AOP(result),0));
12840
12841                         if (((int) operandLitValue(right))) 
12842                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
12843                                         AOP(result)->aopu.aop_dir,
12844                                         AOP(result)->aopu.aop_dir);
12845                         else
12846                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
12847                                         AOP(result)->aopu.aop_dir,
12848                                         AOP(result)->aopu.aop_dir);
12849                         goto release;
12850                 }
12851
12852                 /* the right is also a bit variable */
12853                 if (AOP_TYPE(right) == AOP_CRY) {
12854                         emitCLRC;
12855                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12856
12857                         pic16_emitcode("clrc","");
12858                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
12859                                 AOP(right)->aopu.aop_dir,
12860                                 AOP(right)->aopu.aop_dir);
12861                         pic16_aopPut(AOP(result),"c",0);
12862                         goto release ;
12863                 }
12864
12865                 /* we need to or */
12866                 if (AOP_TYPE(right) == AOP_REG) {
12867                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
12868                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER));
12869                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
12870                 }
12871                 pic16_toBoolean(right);
12872                 pic16_aopPut(AOP(result),"a",0);
12873                 goto release ;
12874         }
12875
12876         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
12877           int offset = 1;
12878
12879                 size = AOP_SIZE(result);
12880
12881                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12882
12883                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
12884                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
12885                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
12886
12887                 while (size--)
12888                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
12889
12890                 goto release;
12891         }
12892
12893         if(IS_BITFIELD(getSpec(restype))
12894           && IS_BITFIELD(getSpec(rtype))) {
12895           DEBUGpic16_emitcode("***", "%d casting a bit to another bit", __LINE__);
12896         }
12897         
12898         /* port from pic14 to cope with generic pointers */
12899         if (PIC_IS_TAGGED(restype))
12900         {
12901           operand *result = IC_RESULT(ic);
12902           //operand *left = IC_LEFT(ic);
12903           operand *right = IC_RIGHT(ic);
12904           int tag = 0xff;
12905
12906           /* copy common part */
12907           int max, size = AOP_SIZE(result);
12908           if (size > AOP_SIZE(right)) size = AOP_SIZE(right);
12909           DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12910
12911           max = size;
12912           while (size--)
12913           {
12914             pic16_mov2w (AOP(right), size);
12915             pic16_emitpcode(POC_MOVWF, pic16_popGet (AOP(result), size));
12916           } // while
12917
12918           /* upcast into generic pointer type? */
12919           if (IS_GENPTR(restype)
12920               && !PIC_IS_TAGGED(rtype)
12921               && (AOP_SIZE(result) > max))
12922           {
12923             /* determine appropriate tag for right */
12924             if (PIC_IS_DATA_PTR(rtype))
12925               tag = GPTR_TAG_DATA;
12926             else if (IS_CODEPTR(rtype))
12927               tag = GPTR_TAG_CODE;
12928             else if (PIC_IS_DATA_PTR(ctype)) {
12929               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__data*)(non-pointer)'\n", ic->filename, ic->lineno);
12930               tag = GPTR_TAG_DATA;
12931             } else if (IS_CODEPTR(ctype)) {
12932               //fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(__code*)(non-pointer)'\n", ic->filename, ic->lineno);
12933               tag = GPTR_TAG_CODE;
12934             } else if (IS_PTR(rtype)) {
12935               PERFORM_ONCE(weirdcast,
12936               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(unknown*)' -- assumimg __data space\n", ic->filename, ic->lineno);
12937               );
12938               tag = GPTR_TAG_DATA;
12939             } else {
12940               PERFORM_ONCE(weirdcast,
12941               fprintf (stderr, "%s:%u: WARNING: casting `(generic*)(non-pointer)' -- assumimg __data space\n", ic->filename, ic->lineno);
12942               );
12943               tag = GPTR_TAG_DATA;
12944             }
12945
12946             assert (AOP_SIZE(result) == 3);
12947             /* zero-extend address... */
12948             for (size = max; size < AOP_SIZE(result)-1; size++)
12949               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size));
12950             /* ...and add tag */
12951             pic16_movLit2f(pic16_popGet(AOP(result), AOP_SIZE(result)-1), tag);
12952           } else if (IS_CODEPTR(restype) && AOP_SIZE(result) > max) {
12953             //fprintf (stderr, "%s:%u: INFO: code pointer\n", ic->filename, ic->lineno);
12954             for (size = max; size < AOP_SIZE(result)-1; size++)
12955               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), size));
12956             /* add __code tag */
12957             pic16_movLit2f (pic16_popGet(AOP(result), AOP_SIZE(result)-1), GPTR_TAG_CODE);
12958           } else if (AOP_SIZE(result) > max) {
12959             /* extend non-pointers */
12960             //fprintf (stderr, "%s:%u: zero-extending value cast to pointer\n", ic->filename, ic->lineno);
12961             pic16_addSign(result, max, 0);
12962           } // if
12963           goto release;
12964         }
12965
12966         /* if they are the same size : or less */
12967         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
12968
12969                 /* if they are in the same place */
12970                 if (pic16_sameRegs(AOP(right),AOP(result)))
12971                         goto release;
12972
12973                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
12974 #if 0
12975                 if (IS_PTR_CONST(rtype))
12976 #else
12977                 if (IS_CODEPTR(rtype))
12978 #endif
12979                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
12980
12981 #if 0
12982                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
12983 #else
12984                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
12985 #endif
12986                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
12987
12988 #if 0
12989                 if(AOP_TYPE(right) == AOP_IMMD) {
12990                   pCodeOp *pcop0, *pcop1, *pcop2;
12991                   symbol *sym = OP_SYMBOL( right );
12992
12993                         size = AOP_SIZE(result);
12994                         /* low */
12995                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12996                         /* high */
12997                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
12998                         /* upper */
12999                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
13000         
13001                         if (size == 3) {
13002                                 pic16_emitpcode(POC_MOVLW, pcop0);
13003                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
13004                                 pic16_emitpcode(POC_MOVLW, pcop1);
13005                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
13006                                 pic16_emitpcode(POC_MOVLW, pcop2);
13007                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
13008                         } else
13009                         if (size == 2) {
13010                                 pic16_emitpcode(POC_MOVLW, pcop0);
13011                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13012                                 pic16_emitpcode(POC_MOVLW, pcop1);
13013                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13014                         } else {
13015                                 pic16_emitpcode(POC_MOVLW, pcop0);
13016                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13017                         }
13018                 } else
13019 #endif
13020                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13021                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
13022                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
13023
13024                         if(AOP_SIZE(result) < 2) {
13025                           fprintf(stderr,"%d -- casting a ptr to a char\n",__LINE__);
13026                         } else {
13027                           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
13028                           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
13029                         }
13030                 } else {
13031                         /* if they in different places then copy */
13032                         size = AOP_SIZE(result);
13033                         offset = 0 ;
13034                         while (size--) {
13035                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
13036                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13037                                 offset++;
13038                         }
13039                 }
13040                 goto release;
13041         }
13042
13043         /* if the result is of type pointer */
13044         if (IS_PTR(ctype)) {
13045           int p_type;
13046           sym_link *type = operandType(right);
13047           sym_link *etype = getSpec(type);
13048
13049                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
13050
13051                 /* pointer to generic pointer */
13052                 if (IS_GENPTR(ctype)) {
13053                   char *l = zero;
13054             
13055                         if (IS_PTR(type)) 
13056                                 p_type = DCL_TYPE(type);
13057                         else {
13058                 /* we have to go by the storage class */
13059                 p_type = PTR_TYPE(SPEC_OCLS(etype));
13060
13061 /*              if (SPEC_OCLS(etype)->codesp )  */
13062 /*                  p_type = CPOINTER ;  */
13063 /*              else */
13064 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
13065 /*                      p_type = FPOINTER ; */
13066 /*                  else */
13067 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
13068 /*                          p_type = PPOINTER; */
13069 /*                      else */
13070 /*                          if (SPEC_OCLS(etype) == idata ) */
13071 /*                              p_type = IPOINTER ; */
13072 /*                          else */
13073 /*                              p_type = POINTER ; */
13074             }
13075                 
13076             /* the first two bytes are known */
13077       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
13078             size = GPTRSIZE - 1; 
13079             offset = 0 ;
13080             while (size--) {
13081               if(offset < AOP_SIZE(right)) {
13082                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3 ptype = 0x%x",__FUNCTION__,__LINE__, p_type);
13083                 pic16_mov2f(AOP(result), AOP(right), offset);
13084 /*
13085                 if ((AOP_TYPE(right) == AOP_PCODE) && 
13086                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
13087                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
13088                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
13089                 } else { 
13090                   
13091                   pic16_aopPut(AOP(result),
13092                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13093                          offset);
13094                 }
13095 */
13096               } else 
13097                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
13098               offset++;
13099             }
13100             /* the last byte depending on type */
13101             switch (p_type) {
13102             case IPOINTER:
13103             case POINTER:
13104             case FPOINTER:
13105                 pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13106                 break;
13107
13108             case CPOINTER:
13109                 pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13110                 break;
13111
13112             case PPOINTER:
13113               pic16_emitcode(";BUG!? ","%d",__LINE__);
13114                 l = "#0x03";
13115                 break;
13116
13117             case GPOINTER:
13118                 if (GPTRSIZE > AOP_SIZE(right)) {
13119                   // assume __data pointer... THIS MIGHT BE WRONG!
13120                   pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA);
13121                 } else {
13122                   pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1));
13123                 }
13124               break;
13125               
13126             default:
13127                 /* this should never happen */
13128                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13129                        "got unknown pointer type");
13130                 exit(1);
13131             }
13132             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
13133             goto release ;
13134         }
13135         
13136         
13137         assert( 0 );
13138         /* just copy the pointers */
13139         size = AOP_SIZE(result);
13140         offset = 0 ;
13141         while (size--) {
13142             pic16_aopPut(AOP(result),
13143                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
13144                    offset);
13145             offset++;
13146         }
13147         goto release ;
13148     }
13149     
13150
13151
13152     /* so we now know that the size of destination is greater
13153     than the size of the source.
13154     Now, if the next iCode is an operator then we might be
13155     able to optimize the operation without performing a cast.
13156     */
13157     if(genMixedOperation(ic))
13158       goto release;
13159
13160     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
13161     
13162     /* we move to result for the size of source */
13163     size = AOP_SIZE(right);
13164     offset = 0 ;
13165
13166     while (size--) {
13167       if(!_G.resDirect)
13168         pic16_mov2f(AOP(result), AOP(right), offset);
13169       offset++;
13170     }
13171
13172     /* now depending on the sign of the destination */
13173     size = AOP_SIZE(result) - AOP_SIZE(right);
13174     /* if unsigned or not an integral type */
13175     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
13176       while (size--)
13177         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
13178     } else {
13179       /* we need to extend the sign :( */
13180
13181       if(size == 1) {
13182         /* Save one instruction of casting char to int */
13183         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
13184         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13185         pic16_emitpcode(POC_SETF,   pic16_popGet(AOP(result),offset));
13186       } else {
13187         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
13188
13189         if(offset)
13190           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13191         else
13192           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
13193         
13194         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
13195
13196         while (size--)
13197           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
13198       }
13199     }
13200
13201 release:
13202     pic16_freeAsmop(right,NULL,ic,TRUE);
13203     pic16_freeAsmop(result,NULL,ic,TRUE);
13204
13205 }
13206
13207 /*-----------------------------------------------------------------*/
13208 /* genDjnz - generate decrement & jump if not zero instrucion      */
13209 /*-----------------------------------------------------------------*/
13210 static int genDjnz (iCode *ic, iCode *ifx)
13211 {
13212     symbol *lbl, *lbl1;
13213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
13214
13215     if (!ifx)
13216         return 0;
13217     
13218     /* if the if condition has a false label
13219        then we cannot save */
13220     if (IC_FALSE(ifx))
13221         return 0;
13222
13223     /* if the minus is not of the form 
13224        a = a - 1 */
13225     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
13226         !IS_OP_LITERAL(IC_RIGHT(ic)))
13227         return 0;
13228
13229     if (operandLitValue(IC_RIGHT(ic)) != 1)
13230         return 0;
13231
13232     /* if the size of this greater than one then no
13233        saving */
13234     if (getSize(operandType(IC_RESULT(ic))) > 1)
13235         return 0;
13236
13237     /* otherwise we can save BIG */
13238     lbl = newiTempLabel(NULL);
13239     lbl1= newiTempLabel(NULL);
13240
13241     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
13242     
13243     if (IS_AOP_PREG(IC_RESULT(ic))) {
13244         pic16_emitcode("dec","%s",
13245                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13246         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13247         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
13248     } else {    
13249
13250
13251       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
13252       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
13253
13254       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
13255       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset);
13256
13257     }
13258     
13259     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13260     ifx->generated = 1;
13261     return 1;
13262 }
13263
13264 /*-----------------------------------------------------------------*/
13265 /* genReceive - generate code for a receive iCode                  */
13266 /*-----------------------------------------------------------------*/
13267 static void genReceive (iCode *ic)
13268 {    
13269
13270   FENTRY;
13271
13272 #if 0
13273   fprintf(stderr, "%s:%d %s for symbol %s\tonStack: %d\n", __FILE__, __LINE__, __FUNCTION__,
13274         OP_SYMBOL( IC_RESULT(ic) )->rname, OP_SYMBOL( IC_RESULT(ic) )->onStack);
13275 #endif
13276 //  pic16_DumpOp(__FUNCTION__, IC_RESULT(ic));
13277
13278   if (isOperandInFarSpace(IC_RESULT(ic))
13279       && ( OP_SYMBOL(IC_RESULT(ic))->isspilt
13280           || IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
13281
13282     int size = getSize(operandType(IC_RESULT(ic)));
13283     int offset =  pic16_fReturnSizePic - size;
13284
13285       assert( 0 );
13286       while (size--) {
13287         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
13288                       fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
13289                       offset++;
13290         }
13291
13292       DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
13293
13294       pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13295       size = AOP_SIZE(IC_RESULT(ic));
13296       offset = 0;
13297       while (size--) {
13298         pic16_emitcode ("pop","acc");
13299         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
13300       }
13301   } else {
13302     DEBUGpic16_emitcode ("; ***","2 %s  %d argreg = %d",__FUNCTION__,__LINE__, SPEC_ARGREG(OP_SYM_ETYPE(IC_RESULT(ic)) ));
13303     _G.accInUse++;
13304     pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
13305     _G.accInUse--;
13306
13307     /* set pseudo stack pointer to where it should be - dw*/
13308     GpsuedoStkPtr = ic->parmBytes;
13309
13310     /* setting GpsuedoStkPtr has side effects here: */
13311     assignResultValue(IC_RESULT(ic), 0);
13312   }
13313
13314   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
13315 }
13316
13317 /*-----------------------------------------------------------------*/
13318 /* genDummyRead - generate code for dummy read of volatiles        */
13319 /*-----------------------------------------------------------------*/
13320 static void
13321 genDummyRead (iCode * ic)
13322 {
13323   operand *op;
13324   int i;
13325
13326   op = IC_RIGHT(ic);
13327   if (op && IS_SYMOP(op)) {
13328     if (IN_CODESPACE(SPEC_OCLS(OP_SYM_ETYPE(op)))) {
13329       fprintf (stderr, "%s: volatile symbols in codespace?!? -- might go wrong...\n", __FUNCTION__);
13330       return;
13331     }
13332     pic16_aopOp (op, ic, FALSE);
13333     for (i=0; i < AOP_SIZE(op); i++) {
13334       // may need to protect this from the peepholer -- this is not nice but works...
13335       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN"));
13336       pic16_mov2w (AOP(op),i);
13337       pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END"));
13338     } // for i
13339     pic16_freeAsmop (op, NULL, ic, TRUE);
13340   } else if (op) {
13341     fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__);
13342   } // if
13343 }
13344
13345 /*-----------------------------------------------------------------*/
13346 /* genpic16Code - generate code for pic16 based controllers        */
13347 /*-----------------------------------------------------------------*/
13348 /*
13349  * At this point, ralloc.c has gone through the iCode and attempted
13350  * to optimize in a way suitable for a PIC. Now we've got to generate
13351  * PIC instructions that correspond to the iCode.
13352  *
13353  * Once the instructions are generated, we'll pass through both the
13354  * peep hole optimizer and the pCode optimizer.
13355  *-----------------------------------------------------------------*/
13356
13357 void genpic16Code (iCode *lic)
13358 {
13359   iCode *ic;
13360   int cln = 0;
13361
13362     lineHead = lineCurr = NULL;
13363
13364     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
13365     pic16_addpBlock(pb);
13366
13367 #if 0
13368     /* if debug information required */
13369     if (options.debug && currFunc) {
13370       if (currFunc) {
13371         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
13372       }
13373     }
13374 #endif
13375
13376     for (ic = lic ; ic ; ic = ic->next ) {
13377
13378       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x\t(%s)",ic->op, ic->op, pic16_decodeOp(ic->op));
13379       if ( cln != ic->lineno ) {
13380         if ( options.debug ) {
13381           debugFile->writeCLine (ic);
13382         }
13383         
13384         if(!options.noCcodeInAsm) {
13385           pic16_addpCode2pBlock(pb, pic16_newpCodeCSource(ic->lineno, ic->filename, 
13386               printCLine(ic->filename, ic->lineno)));
13387         }
13388
13389         cln = ic->lineno ;
13390       }
13391         
13392       if(options.iCodeInAsm) {
13393         char *l;
13394
13395           /* insert here code to print iCode as comment */
13396           l = Safe_strdup(printILine(ic));
13397           pic16_emitpcomment("ic:%d: %s", ic->seq, l);
13398       }
13399
13400       /* if the result is marked as
13401        * spilt and rematerializable or code for
13402        * this has already been generated then
13403        * do nothing */
13404       if (resultRemat(ic) || ic->generated ) 
13405         continue ;
13406         
13407       /* depending on the operation */
13408       switch (ic->op) {
13409         case '!' :
13410           pic16_genNot(ic);
13411           break;
13412             
13413         case '~' :
13414           pic16_genCpl(ic);
13415           break;
13416             
13417         case UNARYMINUS:
13418           genUminus (ic);
13419           break;
13420             
13421         case IPUSH:
13422           genIpush (ic);
13423           break;
13424             
13425         case IPOP:
13426           /* IPOP happens only when trying to restore a 
13427            * spilt live range, if there is an ifx statement
13428            * following this pop then the if statement might
13429            * be using some of the registers being popped which
13430            * would destroy the contents of the register so
13431            * we need to check for this condition and handle it */
13432            if (ic->next
13433              && ic->next->op == IFX
13434              && regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
13435                genIfx (ic->next,ic);
13436           else
13437             genIpop (ic);
13438           break; 
13439             
13440         case CALL:
13441           genCall (ic);
13442           break;
13443             
13444         case PCALL:
13445           genPcall (ic);
13446           break;
13447             
13448         case FUNCTION:
13449           genFunction (ic);
13450           break;
13451             
13452         case ENDFUNCTION:
13453           genEndFunction (ic);
13454           break;
13455             
13456         case RETURN:
13457           genRet (ic);
13458           break;
13459             
13460         case LABEL:
13461           genLabel (ic);
13462           break;
13463             
13464         case GOTO:
13465           genGoto (ic);
13466           break;
13467             
13468         case '+' :
13469           pic16_genPlus (ic) ;
13470           break;
13471             
13472         case '-' :
13473           if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
13474             pic16_genMinus (ic);
13475           break;
13476
13477         case '*' :
13478           genMult (ic);
13479           break;
13480             
13481         case '/' :
13482           genDiv (ic) ;
13483           break;
13484             
13485         case '%' :
13486           genMod (ic);
13487           break;
13488             
13489         case '>' :
13490           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                   
13491           break;
13492             
13493         case '<' :
13494           genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
13495           break;
13496             
13497         case LE_OP:
13498         case GE_OP:
13499         case NE_OP:
13500           /* note these two are xlated by algebraic equivalence
13501            * during parsing SDCC.y */
13502           werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
13503             "got '>=' or '<=' shouldn't have come here");
13504           break;
13505
13506         case EQ_OP:
13507           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
13508           break;            
13509             
13510         case AND_OP:
13511           genAndOp (ic);
13512           break;
13513             
13514         case OR_OP:
13515           genOrOp (ic);
13516           break;
13517             
13518         case '^' :
13519           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
13520           break;
13521             
13522         case '|' :
13523           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
13524           break;
13525             
13526         case BITWISEAND:
13527           genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
13528           break;
13529             
13530         case INLINEASM:
13531           genInline (ic);
13532           break;
13533             
13534         case RRC:
13535           genRRC (ic);
13536           break;
13537             
13538         case RLC:
13539           genRLC (ic);
13540           break;
13541             
13542         case GETHBIT:
13543           genGetHbit (ic);
13544           break;
13545             
13546         case LEFT_OP:
13547           genLeftShift (ic);
13548           break;
13549             
13550         case RIGHT_OP:
13551           genRightShift (ic);
13552           break;
13553             
13554         case GET_VALUE_AT_ADDRESS:
13555           genPointerGet(ic);
13556           break;
13557             
13558         case '=' :
13559           if (POINTER_SET(ic))
13560             genPointerSet(ic);
13561           else
13562             genAssign(ic);
13563           break;
13564             
13565         case IFX:
13566           genIfx (ic,NULL);
13567           break;
13568             
13569         case ADDRESS_OF:
13570           genAddrOf (ic);
13571           break;
13572             
13573         case JUMPTABLE:
13574           genJumpTab (ic);
13575           break;
13576             
13577         case CAST:
13578           genCast (ic);
13579           break;
13580             
13581         case RECEIVE:
13582           genReceive(ic);
13583           break;
13584             
13585         case SEND:
13586           addSet(&_G.sendSet,ic);
13587           break;
13588
13589         case DUMMY_READ_VOLATILE:
13590           genDummyRead (ic);
13591           break;
13592
13593         default :
13594           ic = ic;
13595       }
13596     }
13597
13598
13599     /* now we are ready to call the
13600        peep hole optimizer */
13601     if (!options.nopeep)
13602       peepHole (&lineHead);
13603
13604     /* now do the actual printing */
13605     printLine (lineHead, codeOutFile);
13606
13607 #ifdef PCODE_DEBUG
13608     DFPRINTF((stderr,"printing pBlock\n\n"));
13609     pic16_printpBlock(stdout,pb);
13610 #endif
13611
13612     return;
13613 }
13614